Writing the code for the mathematical operations between my custom classes of vectors and matrices I have faced a strange (at least for me) problem.
The overloaded operators between types give different results in different places. I have dug out that the result of the operation is sensitive on how the new instance is created inside the "operator +(...)".
I have created the simple code showing the difference (see below).
Two classes are making the same thing and the same result is expected, but in reality not the same.
The overloaded operator of Type2 and the function "test" modify the variable.
I have not found any warning about this in MSDN. This behavior is not marked directly by syntax (f.e. by the "ref" keyword).
Can anyone recommend a link about this problem?
Is it predicted behavior or a mistake in the C# syntax?
using System;
namespace test_operator_overload
{
class Program
{
static void Main()
{
Type1 A1 = new Type1(1);
Console.WriteLine(A1); // 1 - OK
Console.WriteLine(A1 + A1); // 2 - OK
Console.WriteLine(A1); // 1 - OK
Console.WriteLine();
Type2 B1 = new Type2(1);
Console.WriteLine(B1); // 1 - OK
Console.WriteLine(B1 + B1); // 2 - OK
Console.WriteLine(B1); // 2 - Not OK
Console.WriteLine();
Type2 C1 = new Type2(1);
Console.WriteLine(C1); // 1 - OK
Console.WriteLine(test(C1)); // 2 - OK
Console.WriteLine(C1); // 2 - Not OK
}
static Type2 test(Type2 a)
{
a.x += 1;
return a;
}
}
class Type1
{
public double x;
public Type1(double x)
{
this.x = x;
}
public static Type1 operator +(Type1 a, Type1 b)
{
return new Type1(a.x + b.x);
}
public override string ToString() { return GetType().Name + " (" + x + ")"; }
}
class Type2
{
public double x;
public Type2(double x)
{
this.x = x;
}
public static Type2 operator +(Type2 a, Type2 b)
{
a.x += b.x;
return a;
}
public override string ToString() { return GetType().Name + " (" + x + ")"; }
}
}
Your + operator for Type2 is borked, you should not modify the inputs in the operators.
Operators operate on the input by combining the inputs and returning the new results.
Related
This is an extension of this question: Is it possible to dynamically compile and execute C# code fragments?
But is it possible to reference fields, properties and methods of a certain object? For example:
public class SomeClass
{
public int a, b;
public int SomeMethod(int a, int b, int c)
{
return a + b + c;
}
public void Execute()
{
int c = 3;
string code = "a = b = 2; int result = SomeMethod(a, b, c);";
// Compile and execute code here
}
}
The code obviously makes no sense in terms of functionality, but it's just an example.
I wouldn't know a way, but you can call string tmp = Path.GetTempFile() to create a temp file and do a code = "void Main(string[] args){int a = b = 2; int result = SomeMethod(a, b, c); File.WriteAllBytes(\"" + tmp + "\", BitConverter.GetBytes(result));" to save the result. Then you can load it with BitConverter.ToInt32(File.ReadAllBytes(tmp)).
I think you're looking for something like Lambda Expression Serializers
DynamicExpresso
I am trying to write some operation overloading and assertion routine.
I have a struct named Degree, and following is my code;
public struct Degree
{
public float InnerValue;
public Degree(float value)
{
InnerValue = value;
}
public static Degree operator +(Degree a, Degree b)
{
return new Degree(a.InnerValue + b.InnerValue);
}
public static void UnitTest()
{
Random rd = new Random();
Degree lhs = rd.NextDegree(-(Degree)360, (Degree)360);
Degree rhs = rd.NextDegree(-(Degree)360, (Degree)360);
float f = rd.NextFloat(-100, 100);
float temp = lhs.InnerValue + rhs.InnerValue;
Debug.Assert((lhs + rhs).InnerValue == temp);
Debug.Assert((lhs + rhs).InnerValue == lhs.InnerValue + rhs.InnerValue);
}
}
my code seems looks very well for operator overloading, but assertion fails.
The problem is only second Assert fails.
I am unable to understand the reason for the same. Any help would be appreciated.
Could someone please explain to me why the result here is: DVD Unknown DVD:DVD
using System;
class Program
{
class M
{
internal string n;
internal M() { }
internal M(string N)
{
Console.Write(N + " ");
n = N;
}
}
class D : M
{
internal D(string N) : base(N) { n = "DVD:" + N; }
}
static void Main(string[] args)
{
M d1 = new D("DVD");
M m1 = new M("Unknown");
Console.WriteLine(" " + d1.n);
}
}
I understand most parts of the code, except for this line:
internal D(string N) : base(N) { n = "DVD:" + N; }
I know that base calls something from the parent class, but in this case i just don't get it. :/
Let's break apart this line:
internal D(string N) : base(N)
{
n = "DVD:" + N;
}
The part you're most likely needing clarification on is base(N). base(N) is a call to the M(string N) constructor. This happens before the body of this constructor (n = "DVD...) is run.
I think the code will be clearer if you modify what is printed slightly:
class M
{
internal string n;
internal M() { }
internal M(string N)
{
Console.WriteLine("in base " + N);
n = N;
}
}
class D : M
{
internal D(string N) : base(N) { n = "DVD:" + N; }
}
static void Main(string[] args)
{
M d1 = new D("DVD");
M m1 = new M("Unknown");
Console.WriteLine("d1.n is " + d1.n);
}
Outputs
in base DVD
in base Unknown
d1.n is DVD:DVD
The same thing is happening in your output of DVD Unknown DVD:DVD, just all on one line: first, D's constructor calls M's constructor, which writes DVD (this happens before DVD: is added to it). Then, M's constructor is called directly, which writes Unknown. Then, you write d1's n, which is DVD:DVD.
First of all, Console.WriteLine(" " + d1.n); will give you DVD:DVD because base means use the parent class' constructor. So, when you send your parameters into your D class, it is sending your code to your M class, it is executing it which gives you "DVD" on your screen and then it is changing the value of n. After that you are sending the "Unknown" value your M class directly which is not related with your D class anymore and it is showing you "Unknown" on your screen. At the end you are requesting D class' n value which is already "DVD". So the result is DVD Unknown DVD:DVD. I hope this makes sense for you.
I am learning C# for a new position, and to try and understand classes better, I've written a short die-rolling tool to help me. The code essentially rolls four d6, adds the total, and subtracts the smallest die roll. The code is generated through a form, and the form shows all the rolled values, as well as the subtracted for error checking. Here's the code:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public static int d1 = 0;
public static int d2 = 0;
public static int d3 = 0;
public static int d4 = 0;
public static int sum = 0;
public Form1()
{
InitializeComponent();
}
private void form_description_Click(object sender, EventArgs e)
{
}
private void roll_button_Click(object sender, EventArgs e)
{
Random random_number = new Random();
d1 = random_number.Next(1, 7);
d2 = random_number.Next(1, 7);
d3 = random_number.Next(1, 7);
d4 = random_number.Next(1, 7);
sum = Math.Min(Math.Min(Math.Min(d1, d2), d3), d4);
label_d1.Text = "Value of D1 is: " + d1;
label_d2.Text = "Value of D2 is: " + d2;
label_d3.Text = "Value of D3 is: " + d3;
label_d4.Text = "Value of D4 is: " + d4;
label_sum.Text = "Value of Sum is: " + sum;
attribute_roll.Text = "Your strength is: " + ((d1 + d2 + d3 + d4) - sum);
}
}
}
The program works, so I know I'm on the right track. The problem I have is converting it into a class. I've tried several times, over and over, and I get different errors everywhere I turn. So for converting this program into a class, my key questions are:
Is it possible to use Random, a pre-existing class, in my own class? Or do I need to declare that in the form itself?
If I use "public static int" in the class, will the values transfer to the method? I've not understood clearly the difference between "public int" and "public static int"?
1. It's possible to use it in your own class, you'd just define it in the class scope.
class Foo
{
Random rng = new Random();
...
}
2. Static members don't require an instance to be accessed, therefore they are global to the entire program, non-static members are tied to an instance.
class Foo
{
public static int Bar = 42;
public int Baz = 42;
}
Console.WriteLine( Foo.Bar ); //OK, static variables don't require the class to be instantiated.
Console.WriteLine( Foo.Baz ); //Error, Baz is not static.
Foo foo_instance = new Foo();
Console.WriteLine( foo_instance.Baz ); //OK
Note that because of this, changing a static variable from inside an instance method will change it globally as well.
class Foo
{
public static int Bar = 42;
public void Baz()
{
Bar = Bar + 1;
}
}
Console.WriteLine( Foo.Bar ); //42
Foo foo_instance = new Foo();
foo_instance.Baz();
Foo foo_instance2 = new Foo();
foo_instance2.Baz();
Console.WriteLine( Foo.Bar ); //44
So the values of your d1, d2, d3, d4, and sum variables can be changed outside the main instance of Form1 if you have multiple instances and cause unexpected results.
The Random class also resides in the System namespace, so if that's giving errors, you need to include using System; at the top of your file.
Let me answer your two questions exactly as you asked them:
1) It is possible to use Randomin your class. It doesn't need to be in the form
2) You can use static variables from static and non-static methods, but you can't use non-static variables from static methods.
Thumbs up! The fact that you found out that classes might help in your situation is the first step to write better rpograms. Try to find a tutorial online which covers the principles of object oriented design. This is something you'll really benefit from, independent of the actual programming language.
My suggestion: invest 50$ for one month of unlimited Pluralsight trainings. Pick a C# fundamentals or C# from scratch course and follow the examples by re-implementing them.
It took a lot of trial and error, but I managed to convert my code into a class. Unfortunately, I'm not 100% sure I understand what I DID. Here's the code for the class:
public class four_d6_less_one
{
////Variables declared here.
public static int dice1;
public static int dice2;
public static int dice3;
public static int dice4;
public static int minus_low;
public static int sum_dice;
//This is the constructor
public four_d6_less_one()
{
Random rand_dice = new Random();
dice1 = rand_dice.Next(1, 7);
dice2 = rand_dice.Next(1, 7);
dice3 = rand_dice.Next(1, 7);
dice4 = rand_dice.Next(1, 7);
minus_low = Math.Min(Math.Min(Math.Min(dice1, dice2), dice3), dice4);
sum_dice = dice1 + dice2 + dice3 + dice4 - minus_low;
}
And here is the code for the form itself:
private void roll_button_Click(object sender, EventArgs e)
{
four_d6_less_one make_it_roll = new four_d6_less_one();
label_d1.Text = "Value of D1 is: " + four_d6_less_one.dice1; //This is where dice1 goes
label_d2.Text = "Value of D2 is: " + four_d6_less_one.dice2; //This is where dice2 goes
label_d3.Text = "Value of D3 is: " + four_d6_less_one.dice3; //This is where dice3 goes
label_d4.Text = "Value of D4 is: " + four_d6_less_one.dice4; //This is where dice4 goes
label_sum.Text = "Value of Sum is: " + four_d6_less_one.minus_low; //This is where minus_sum goes
attribute_roll.Text = "Your strength is: " + four_d6_less_one.sum_dice; //This totals all variables and subtracts minus_sum
}
Here's what I'm not sure I understand:
Why did I have to declare "make_it_roll" to make the code work?
Without that line, the form just displays null values. Is it
because I had to create a new instance of the class to activate it?
Why did I have to call variables by saying "four_d6_less_one.dice1"
and so forth? Why couldn't I just put "dice1" as a variable?
Was there a more efficient way to write this code (I'm sure there always
is, but I'm wondering if I missed something).
I have this in my main:
static void Main(string[] args)
{
Money m1 = new Money(2315.99);
Money m2 = new Money(4000, 25);
Console.WriteLine(m1);
Console.WriteLine(m2);
Console.WriteLine(m1.IncrementMoney(m2));
}
public void IncrementMoney(Money x)
{
//what do I put in here?
}
So
Money m1 = new Money(2315.99); is supposed to turn 2315.99 into "$2315.99"
and
Money m2 = new Money(4000, 25); forms "$4000.25"
I have all that done in Money class and it works fine.
Now what I'm supposed to do is add those two together using
m1.IncrementMoney(m2);
This is my "Money" class
class Money
{
//instance variables
private int dollars;
private int cents;
double amount;
public int Dollars
{
get { return dollars; }
set
{
if (value > 0)
dollars = value;
}
}
public int Cents
{
get { return cents; }
set
{
if (value > 0)
cents = value;
}
}
public Money(int Dol, int Cen)
{
Dollars = Dol;
Cents = Cen;
double Dollar = Convert.ToDouble(Dollars);
double Cent = Convert.ToDouble(Cents);
amount = Dollar + (Cent / 100);
}
public Money(double am)
{
int dol = Convert.ToInt32(am);
if (dol > am)
Dollars = dol - 1;
else if (dol < am)
Dollars = dol;
//Dollars
double cen = am % 1;
cen = cen * 100;
Cents = Convert.ToInt32(cen);
//Cents
double Dollar = Convert.ToDouble(Dollars);
double Cent = Convert.ToDouble(Cents);
amount = Dollar + (Cent / 100);
}
//override ToString()
public override string ToString()
{
return string.Format("{0:c}", amount);
}
}//end class Money
But I have no idea what to put into the IncrementMoney method. Please help?
and if not too much trouble, maybe a little insight to how it works? I'd really like to know.
Sorry if I didn't give enough info,
If anything else is required please let me know.
and thanks!
Since IncrementMoney is supposed to add the two money values together, your usage looks like it should instead be an extension method of the Money type. Which is fine, because extension methods are pretty awesome. A common joke on this site is that they're the solution to everything.
Your code should look similar to:
public static Money IncrementMoney(this Money x, Money y)
{
var totalCents = x.Cents + y.Cents;
var retCents = totalCents / 100;
var retDollars = x.Dollars + y.Dollars + (totalCents % 100)
return new Money(retDollars, retCents);
}
As for a quick explanation...
By adding this to the first argument, we are telling C# that we want to write an extension method. This will mean that this method we're writing will hang off the type of the this argument (in this case, Money) and allow us to use it exactly like it was always in the .NET framework. Extension methods have to be static, so you can't not use that modifier. Beyond that, you just write a method to do whatever you have in mind, exactly like you normally would!
I would suggest you name it something other than IncrementMoney, though. That's not very descriptive. AddMoney would be better.
You may also look into operator overloading, by the way. You could adapt what I just wrote to simply use the + operator to do exactly the same thing, like so:
public static Money operator +(Money x, Money y)
{
var totalCents = x.Cents + y.Cents;
var retCents = totalCents / 100;
var retDollars = x.Dollars + y.Dollars + (totalCents % 100)
return new Money(retDollars, retCents);
}
With this defined, you can simply go m1 + m2 and add them together.
public void IncrementMoney(Money x)
{
this.Dollars += x.Dollars;
var newCents = this.Cents + x.Cents;
this.Cents = newCents % 100;
this.Dollars += newCents / 100;
}
And I would actually name the function Add since you are taking the current value and adding the provided value, and no need for the Money modifier as it should be on the Money class and takes a Money object
Well first of all this line:
Console.WriteLine(m1.IncrementMoney(m2));
indicates that IncrementMoney should return something, but right now it returns void.
So it looks like it should be something like:
public void IncrementMoney(ClassA x)
{
this.Value += x.Value;
}
And then display it with:
ClassA m1 = new ClassA(2315.99);
ClassA m2 = new ClassA(4000, 25);
Console.WriteLine(m1);
Console.WriteLine(m2);
m1.IncrementMoney(m2);
Console.WriteLine(m1);