C# Adding classes with one another - c#

So I was playing around with "Vectors" in C# I created my own Vector class.
What I tried to do was to add two vectors with each other by a simple "+".
This is my vector class:
class createVector
{
//My x,y,z coordinates
public int x { get; set; }
public int y { get; set; }
public int z { get; set; }
//constructor
public createVector(int X, int Y, int Z=0)
{
x = X;
y = Y;
z = Z;
}
// Convert to String
public override string ToString()
{
return string.Format("X:{0,-5}\nY:{1,-5}\nZ:{2,-5}", x, y, z);
}
}
And what I attempted to do was this:
createVector Vector1 = new createVector(1, 2);
createVector Vector2 = new createVector(3, 4, 5);
createVector Vector 3 = Vector1 + Vector2;
I don't want to use a function to add the Vectors together.
Is it possible for me to do something like this?

You need to overload the + operator inside the class:
public static Vector operator +(Vector v1, Vector v2)
{
// do logic here then return a vector
return new Vector ();
}
It is better to follow .NET naming conventions and have your class named Vector and not createVector. It should be a noun and using PascalCase .

Related

Make struct pointing to different struct in C# [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 months ago.
Improve this question
class IntComponent
{
public int size;
}
class IntReferenceComponent : IntComponent
{
public IntComponent target; // keep my size same as target size
private void OnValidate()
{
//triggered on target assignment
}
}
Is it possible in C# make struct variable pointing to different struct variable like with objects ? Even with unsafe pointers ?
Edit
The final solution according to Charlieface solution:
public abstract class StructComponent<T> where T : struct
{
public T size;
}
public class IntComponent : StructComponent<int>{ }
public class IntReferenceComponent : IntComponent
{
public IntComponent target;
public new int size
{
get => target.size;
set => target.size = value;
}
}
In Unity I had to create custom editor:
public abstract class StructComponentEditor<T, D> : Editor where T : struct where D : StructComponent<T>
{
public static object StructField(string label, T value, params GUILayoutOption[] options)
{
switch (value)
{
case Vector3 v:
return EditorGUILayout.Vector3Field(label, v, options);
case Vector2 v:
return EditorGUILayout.Vector2Field(label, v, options);
case float f:
return EditorGUILayout.FloatField(label, f, options);
case int i:
return EditorGUILayout.IntField(label, i, options);
case double d:
return EditorGUILayout.DoubleField(label, d, options);
case Color c:
return EditorGUILayout.ColorField(label, c, options);
}
return null;
}
public void DrawDefaultStructComponent()
{
D target = serializedObject.targetObject as D;
PropertyInfo sizeProp = target.GetType().GetProperty("size");
object value;
try
{
value = sizeProp.GetValue(target);
}
catch
{
value = new T();
}
if(sizeProp.SetMethod != null)
{
sizeProp.SetValue(target, StructField("Size", (T)value));
return;
}
StructField("Size", (T)value);
}
public override void OnInspectorGUI()
{
DrawDefaultStructComponent();
DrawDefaultInspector();
}
}
[CustomEditor(typeof(StructComponent<int>), true)]
[CanEditMultipleObjects]
public class IntComponentEditor : StructComponentEditor<int, StructComponent<int>> { }
I need to write something because most of it is just code :)))))) So thanks to everyone who helped :) I love you <3
You don't need to do this in your case, and generally it would be ill-advised to try and mess around with pointers in normal Object Oriented cases, as you don't normally expose the internals of a class.
Instead, just use composition, with an outer property exposing the value of the inner object
class IntReferenceComponent : IntComponent
{
public IntComponent target; // keep my size same as target size
public int Size
{
get => target.size;
set => target.size = value;
}
}
You Can not do this with struct since its value type means you only can take a copy from it and you can't use it as a pointer as you do with classes
Below Code shows that even with pointers unsafe code will not work because you, in the end, will copy the values to a struct to use them,
since you can't access the object attribute with the pointer that
just `point to the object itself (this is what I know )
namespace Feto
{
internal struct Complex
{
public float real;
public float imag;
public Complex(float real, float image)
{
this.real = real;
this.imag = image;
}
public override string ToString()
{
return $" Class Complex {this.real} , {this.imag}";
}
}
class FixingComplex
{
public float real;
public float imag;
public FixingComplex(float real, float image)
{
this.real = real;
this.imag = image;
}
public override string ToString()
{
return $" Class Complex {this.real} , {this.imag}";
}
}
unsafe class program
{
public static void Main()
{
Complex x = new Complex(10, 20);
Console.WriteLine(x);
Complex* y = &x;
//address of stuct
Console.WriteLine((int)&x);
//the y point to it
Console.WriteLine((int)y);
//what z point to
Console.WriteLine(*y);
//send the addresss of the stuct
addNumbers(y);
Console.WriteLine(x);
Console.ReadKey();
void addNumbers(Complex* result)
{
//make sure it is the same address of stuct
Console.WriteLine((int)result);
//now here we got the address of struct we need to modify it
Console.WriteLine(*result);
//Here is the problem it will take copy
var value = *result;
value.real = 8888;
value.imag = 8888;
//you can use fixedcomplex to go on with pointers and workaround
.....
}
}
}
}
But there is a Solution
with small modifications like passing the address as a reference, not a copy of the address this will workaround and change the values and
The Changes addNumbers(ref y); void addNumbers(ref Complex* result) *result = new Complex(8888,8888);
namespace Feto
{
internal struct Complex
{
public float real;
public float imag;
public Complex(float real, float image)
{
this.real = real;
this.imag = image;
}
public override string ToString()
{
return $" Class Complex {this.real} , {this.imag}";
}
}
class FixingComplex
{
public float real;
public float imag;
public FixingComplex(float real, float image)
{
this.real = real;
this.imag = image;
}
public override string ToString()
{
return $" Class Complex {this.real} , {this.imag}";
}
}
unsafe class program
{
public static void Main()
{
Complex x = new Complex(10, 20);
Console.WriteLine(x);
Complex* y = &x;
//address of stuct
Console.WriteLine((int)&x);
//the y point to it
Console.WriteLine((int)y);
//what z point to
Console.WriteLine(*y);
//send the addresss of the stuct
addNumbers(ref y);
Console.WriteLine(x);
Console.ReadKey();
void addNumbers(ref Complex* result)
{
//make sure it is the same address of stuct
Console.WriteLine((int)result);
//now here we got the address of struct we need to modify it
Console.WriteLine(*result);
//Here is the problem it will take copy
//var value = *result;
*result = new Complex(8888,8888);
//you can use fixedcomplex to go on with pointers and workaround
}
}
}
}

Pass variable to class implemented in a script loaded with Roslyn

I'm trying to implement a script evaluator to evaluate some classes that my users will implement that will have a fixed entry point accepting a variable that will be given from the main application.
To do this I've declared a namespace that contains the type of the object that will be passed to the entry point. This is the whole code that declares the custom type and executes the scripts:
namespace MyNamespace
{
public class Vertex
{
public float X { get; } = 0.0f;
public float Y { get; } = 0.0f;
public float Z { get; } = 0.0f;
public Vertex(float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
public override string ToString()
{
return string.Format("[{0}, {1}, {2}]", X, Y, Z);
}
}
}
public class Globals
{
public Vertex testVertex = new Vertex(0, 0, 0);
public int testValue = 100;
}
class Program
{
static void Main(string[] args)
{
try
{
ScriptOptions options = ScriptOptions.Default;
// Add assemblies
options = options.AddReferences(
typeof(System.Object).GetTypeInfo().Assembly,
typeof(System.Linq.Enumerable).GetTypeInfo().Assembly,
typeof(MyNamespace.Vertex).GetTypeInfo().Assembly
);
// Add usings
options = options.AddImports("System");
options = options.AddImports("System.Linq");
options = options.AddImports("System.Collections.Generic");
options = options.AddImports("MyNamespace");
var script = <added below>;
Globals globals = new Globals();
ScriptState<object> scriptState = CSharpScript.RunAsync(script, options: options, globals: globals).Result;
scriptState = scriptState.ContinueWithAsync(#"Figure fig = new Figure();").Result;
scriptState = scriptState.ContinueWithAsync(#"fig.Draw(testVertex);").Result;
}
catch (CompilationErrorException e)
{
Console.WriteLine(string.Join(Environment.NewLine, e.Diagnostics));
}
}
}
And this is an example of a script that I'm trying to load:
public class Figure
{
public void Draw(Vertex v)
{
System.Console.WriteLine(v.ToString());
}
public void Draw(int i)
{
System.Console.WriteLine(i);
}
}
Now, the problem is that when I call the method Draw of the class Figure inside the script, it throws me an exception saying
error CS1503: Argument 1: cannot convert from 'MyNamespace.Vertex [~/Projects/ScriptTest/ScriptTest/bin/Debug/netcoreapp1.0/ScriptTest.dll]' to 'MyNamespace.Vertex [ScriptTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]'
When I do
scriptState = scriptState.ContinueWithAsync(#"fig.Draw(testValue);").Result; // Using testValue instead of testVertex
everything works fine.
It think the problem is that the script is referring to a different namespace than MyNamespace but I don't know how to solve this.

How a function can be automatically called upon a variable change?

I have a class consisting of variable members and a function member. The variable member occasionally changes. I want the function to be called automatically upon the variable changes. In other words, how can I tie the variables inside a class?
class line
{
double x, y; // The poition of the lind end. The line starts at the origin (0,0)
double l; // The length of the line
void length()
{
l = Math.sqrt(x*x+y*y);
}
}
In example above, I need the length to be updated when x and y change.
Make your variables into properties, then put your functions in the set accesors.
class line
{
double _x, _y;
double x
{
get { return _x; }
set
{
_x = value;
length();
}
}
double y
{
get { return _y; }
set
{
_y = value;
length();
}
}
double l; // The length of the line
void length()
{
l = Math.Sqrt(_x * _x + _y * _y);
}
}
If you define properties, on your class, you can make X and Y autoprops, then make a read-only property L that is calculated from these values:
public class Line //class names should be Capitalized
{
public double X{ get; set; } //prop names should be Capitalized
public double Y{ get; set; }
public double L{
get{
return Math.Sqrt(X * X + Y * Y);
}
}
}
you can you properties
int x
int X {
get { return x; }
set { x = value; YouMethod();}
}
You can achieve pretty similar behavior using calculated property like
double Length
{
get { return Math.sqrt(x*x+y*y); }
}
The only caveat is that calculation is performed upon each call to Length even if x and y haven't changed.
You can encapsulate you x and y fields into properties and call length function from setter like
double X
{
get { return x; }
set
{
x = value;
length();
}
}
double Y
{
get { return y; }
set
{
y = value;
length();
}
}
and then change x and y ONLY via X and Y properties.
As BenJ noted, you can use properties.
Instead of declaring x and y as simple fields inside the class. You can declare them as properties the following way :
private double x;
public double X
get
{
return this.x;
}
set
{
this.x = value;
this.length()
//Above line will call your desired method
}

Vector math dimension consistency check at compile-time

I am creating a linear algebra library in C#, and I would like to force dimension inconsistency errors up to compile-time. I've implemented a similar solution to this, where the trait I use is a class that uniquely maps to an integer. The problem is for every possible size I would like my Vectors to have, I would need to create a class with a unique name to represent it.
Here is an example of that implementation:
public class Vector<T> where T: ISize, new()
{
static readonly T size = new T();
List<double> values;
public Vector(List<double> values)
{
if (values.Count != size.Size)
throw new IndexOutOfRangeException();
this.values = new List<double>(values);
}
public double Get(int index)
{
return values[index];
}
public Vector<T> Add(Vector<T> other)
{
var vv = new List<double>();
for (int ii = 0; ii < size.Size; ++ii)
vv.Add(other.Get(ii) + this.values[ii]);
return new Vector<T>(vv);
}
}
public interface ISize
{
int Size { get; }
}
public class S1 : ISize
{
public int Size
{
get { return 1; }
}
}
public class S2 : ISize
{
public int Size
{
get { return 2; }
}
}
And here's an example of its usage:
class Program
{
static void Main(string[] args)
{
var v1 = new Vector<S2>(new List<double>() { 1, 2 });
var v2 = new Vector<S2>(new List<double>() { 10, -4 });
var z1 = new Vector<S1>(new List<double>() { 10 });
// works
var v3 = v1.Add(v2);
// complie-time error
var z2 = z1.Add(v1);
}
}
This works quite well for my purposes, except for the fact that I would need to create a different implementation of ISize for every possible Vector size. Is there any way for me to implement the Vector class that would allow me to get around this problem?
In order to get a compile-time error, you need to have different types. C# does not have a concept that let's you define a type parameter that itself takes a kind of value parameters - which is what you would need to do this.
Therefore, I don't think what you are asking is possible.
I think there might be a way to make unique types for family of vector instances using anonymous types, but that's going to be quirky and I don't think it would provide the type safety that you want.
C++ has such a concept in templates (so it's not unreasonable), just not possible in C#.
You can create a single N-dimentional Vector class with compile time type checking, but it's pretty messy. What we're creating here is LISP style linked-lists, but through generic type arguments rather than purely out of object references via fields.
public interface IVector
{
double Value { get; }
IVector Tail { get; }
}
public class Vector<T> : IVector
where T : IVector
{
internal Vector(double value, T tail)
{
Value = value;
Tail = tail;
}
public double Value { get; private set; }
public T Tail { get; private set; }
public Vector<Vector<T>> Add(double value)
{
return new Vector<Vector<T>>(value, this);
}
}
internal class EmptyVector : IVector
{
public double Value
{
get { throw new NotImplementedException(); }
}
public IVector Tail
{
get { return null; }
}
}
public static class Vector
{
public static readonly Vector<IVector> Empty = new Vector<IVector>(
0, new EmptyVector());
public static IEnumerable<double> AllValues(this IVector vector)
{
IVector current = vector;
while (current != Vector.Empty && current != null)
{
yield return current.Value;
current = current.Tail;
};
}
}
This allows us to write:
var v1 = Vector.Empty.Add(1).Add(2);
var v2 = Vector.Empty.Add(10).Add(-4);
var z1 = Vector.Empty.Add(10);
v1 = v2;//works, as they are the same type
z1 = v2;//fails, as they aren't the same type, since they're a different size
This allows allows you to write a method that accepts a vector of a particular size. It's not convenient, and it doesn't scale, but it works. If you want, say, a 3D vector as a parameter, you can write:
public static void Foo(Vector<Vector<Vector<IVector>>> vector)
{
var first = vector.Value;
var second = vector.Tail.Value;
var third = vector.Tail.Tail.Value;
}

Use a struct as a multidimensional array index

I have a 3D array that I'm accessing this way Array(int x, int y, int z). What I would like to know, if it is possible to have a struct, that has xyz in it, so that I can use it this way: Array(struct xyz). If it is, then how?
The reason for why I would want this, is that it would be easier for me to read and write, and that it would be alot simpler and less error prone to write. Makes it easier to maintain the bigger picture.
I do know that I could make a class that has its own method, but since I have many classes and applying it to each one would make me quickly loose the readability, using the struct directly would be a better option if available.
Example:
public struct xyz
{
public int x, y, z;
public xyz(int X, int Y, int Z)
{
x = X;
y = Y;
z = Z;
}
}
private void Test()
{
int(,,) Array = new int()
{
{
{0,0},
{0,0},
},
{
{0,0},
{0,0},
}
};
xyz XYZ = new xyz(0,0,0);
Array[XYZ] = 1; // this instead of
Array[XYZ.x, XYZ.y, XYZ.z] = 1 // this
}
You could create your own array class that wraps a real array, and provides an indexer to do what you want:
class MyArray<T>
{
private T[,,] array;
public MyArray(int xSize, int ySize, int zSize)
{
array = new T[xSize,ySize,zSize];
}
public T this[XYZ xyz]
{
get { return array[xyz.x, xyz.y, xyz.z]; }
set { array[xyz.x, xyz.y, xyz.z] = value; }
}
}
You can easily achieve that by creating your own collection that can be accessed either by specifying all thee coordinates separately:
public T this[int x, int y, int z] { get { … } set { … } }
Or by your XYZ struct:
public T this[XYZ xyz] { get { … } set { … } }
You can't add that indexer to array, extension indexers are not possible. What you could do is to create two extension methods. Something like:
public static T Get<T>(this T[,,] array, XYZ xyz)
{
return array[xyz.X, xyz.Y, xyz.Z];
}
public static void Set<T>(this T[,,] array, XYZ xyz, T value)
{
array[xyz.X, xyz.Y, xyz.Z] = value;
}
And then use it like this:
int i = array.Get(xyz);
array.Set(xyz, 25);
Also, creating mutable structs, like you did, is considered worst practice in C#. They can be very confusing.
Completing the solution of #Andrew Cooper, if you also want to access that matrix normally you must add this methods (Look at the end of Andrew's code)
class MyArray<T>
{
private T[,,] array;
// Constructor
public MyArray(int xSize, int ySize, int zSize)
{
array = new T[xSize,ySize,zSize];
}
// Index with your own struct XYZ
public T this[XYZ xyz]
{
get { return array[xyz.x, xyz.y, xyz.z]; }
set { array[xyz.x, xyz.y, xyz.z] = value; }
}
// Normal index
public T this[int x, int y , int z]
{
get { return array[x, y, z]; }
set { array[x, y, z] = value; }
}
// Get dimensions
public int GetLength(int dim)
{
return array.GetLength(dim);
}
}

Categories