Manipulating variables in structs in C# - c#

I'm messing around trying to learn C# in Visual Studio. I have only basic coding knowledge, and I bought C# 5.0 in a nutshell. I'm loving the book, and trying to make mini programs out of everything I read to help make it stick. I thought structs were something simple, but for whatever reason I just can't get a struct to work.
So here's a brief and ultra basic example from the book.
public struct Point {
int x, y;
public Point(int x, int y) { this.x = x; this.y = y; }
}
Point p1 = new Point();
Point p2 = new Point(1, 1);
It works fine. But now say I want to manipulate the x and y variables in p1 or p2. I've tried so much, and I can't get it to work.
public struct Point {
public int x;
}
Point p1 = new Point();
p1.x = 10;
This won't work. When I try to set p1.x to 10, I get an error. It says p1 is a "field" but is used like a "type."
There's probably something simple I'm missing, but my patience for trial and error has run out. So what am I doing wrong? I understand the basic concept of why a struct is useful, but I need to be able to actually use it once I make it!

Tono Nam's answer is correct but incomplete.
To set the values of x and y the way you want to, you will also need to set the correct access modifier for x and y e.g.
class Program
{
public struct Point
{
public int x, y;
public Point(int x, int y) { this.x = x; this.y = y; }
}
static void Main(string[] args)
{
var p1 = new Point();
var p2 = new Point(1, 1);
p1.x = 1;
p1.y = 1;
}
}
You'll want to use public to access x and y from any class.
You'll want to use internal if you only want to access x and y from within the same class where the struct Point is defined.

class Program
{
public struct Point
{
int x, y;
public Point(int x, int y) { this.x = x; this.y = y; }
}
static void Main(string[] args)
{
Point p1 = new Point();
Point p2 = new Point(1, 1);
}
}
Just like #pst mentioned. p1 and p2 need to be inside a method. In this case they are inside the main method.

Related

Why does all members of a class show error 'CS0103'

I'm testing a piece of code in c# and vs2022, but I encounter some problems. I try to track the value of some members in a class, but the VS2022 shows error CS0103.
So I would like to know why VS2022 can't show their values because they are certainly in this context.
class Program
{
static void Main(string[] args)
{
ProtoType p = new ProtoType(100, 200);
p.x = 101;
p.y = 20;
int cnt = p.list.Count;
Console.ReadLine();
}
}
class ProtoType
{
public int x = 0;
public int y = 0;
public List<string> list = new List<string>();
public ProtoType(int x, int y)
{
Console.WriteLine("Execute Constructor ProtoType()");
this.x = x;
this.y = y;
}
public ProtoType Clone()
{
Console.WriteLine("Execute ProtoType.Clone()");
return (ProtoType)this.MemberwiseClone();
}
}
Because x, y and list are not variables in this scope. they are members of the class ProtoType. you need to watch for p.x, p.y and p.list in place of the x, y, list.

Why is this nested struct creation slower than un-nested?

I've been benchmarking some C# struct creation, and I've been surprised to find that creation of a nested struct is significantly slower than the un-nested version. I would have expected the JITter to basically produce the same assembly for a flat and nested structure, but this appears to not be the case.
Does anyone have an explanation for why the struct construction in my test code below doesn't get optimized down to just writing the 3 doubles? It seems to (if I'm reading the assembly correctly) zero and create a temporary memory location before writing the values to the final location - presumably actually creating a temporary copy of the nested struct.
And in the follow-up, is there a way to avoid this extra work such that the nested struct has similar creation speed to the un-nested one?
public class StructBenchmarks
{
public struct Vector3_dp
{
public Vector3_dp(double x, double y, double z)
{
X = x;
Y = y;
Z = z;
}
public double X;
public double Y;
public double Z;
}
public readonly struct ContainsVector
{
public ContainsVector(double x, double y, double z)
{
m_vector = new Vector3_dp(x, y, z);
}
public ContainsVector(Vector3_dp input)
{
m_vector = input;
}
private readonly Vector3_dp m_vector;
}
private ContainsVector m_vector1;
private ContainsVector m_vector2;
private Vector3_dp m_vector3_dp1;
private Vector3_dp m_vector3_dp2;
// 0.2ns
public void Vector3_dp_Construction()
{
m_vector3_dp1 = new Vector3_dp(20, 30, 40);
}
// 3.8ns
public void Vector_Construction()
{
m_vector1 = new ContainsVector(20, 30, 40);
}
// 3.8ns
public void Vector_ConstructionFromVector3_dp()
{
m_vector1 = new ContainsVector(m_vector3_dp1);
}
// ~0ns
public void Vector3_dp_Copy()
{
m_vector3_dp1 = m_vector3_dp2;
}
// ~0ns
public void Vector_Copy()
{
m_vector1 = m_vector2;
}
}
And SharpLab link: https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AXEBDAzgWwB8BYAKAAJLyABAZhoCZyBlDKAVzAwCEYA7MAAt82KAGtcZKuQDeU6VTrlcbThnIA1GF2i0A+gBMADvIWzTZxfS06o+4wAoDEdsAA2McgjTlnrj+QAnj5+7p4AXgCUFpbmFLGWABrkALxeANwxCZQAmqlBmfHZ0gBa+eGFxeQAvmRZZkqhAYmVxY0uYeQ5rdnt/p4lPQq1pPU09LDYznxugcqqXOQAwhB8GNgAlny4NhjQY3JFCUora5vbu9BOHQHevjeewff95FFj0odV0vh6AG7aeyg+T4MAA7poAbpDEYHHcnlEhrERu8rMtVustjtIVAHJc7NDyFsjOwMNEjrFPl9KD9/rZ8kSSYjLMjyZYjFANr9sBhPJNprMIbZ7EZyDTsUzKCzYuzOdzPKcMRdsaK/tiAIwS8gyrk8tFnTF4lW0wEMQpjbVywWA4VG7HCjXmjk6zx4m1ioXQ011VmUAD0vvIAAYAHQMbZjJTUFBWqHGPSnFQcLgbVYOMkUlHU1Ue4xq4FgmP4xwMQM+Wil8goQORTVSyz+8i0YMADnDPvGNGjePjq0TahTfDTB0zttsebSIPBCvOWNsDhLZYrVZrYzrZgbTdbknbka72J72wWGAHADEoBB8K7oUP25Tsu7AePyJO9YrZ4CHA/Y0Y1Sv22uFF3QthR7IxAhvDN22+bNrWhJ8vyLIwvX/MYI3oKNC1A8D00sO8EgQ+CYOgZCkQsEYgA=

C# Constructor breaks due to another constructor

I have a C# point class with multiple constructors in a library (This is a different class than a System.Drawing.Point in .NET).
Public class Point {
public float X;
public float Y;
public float Z;
//Constructor 1
public Point(float x, float y, float z) {
this.X = x;
this.Y = y;
this.Z = z;
}
//Constructor 2
public Point(Point point) {
this.X = point.X;
this.Y = point.Y;
this.Z = point.Z;
}
//Constructor 3
public Point(PointF point) {
this.X = point.X;
this.Y = point.Y;
this.Z = 0;
}
//Constructor 4
public Point(System.Drawing.Point point) {
this.X = point.X;
this.Y = point.Y;
this.Z = 0;
}
}
When I am trying to create a new Point object using the constructor that takes in float as parameters, everything works fine. When I want to create a new Point using an existing Point object (Constructor 2), I receive an error saying that I need to reference the System.Drawing assembly. I am guessing this is because of constructors 3 and 4 since they take a System.Drawing.Point and a PointF as an argument, but I don't see why they should pose an issue, since the constructor I am trying to use is completely unrelated to them, and constructor 1 works fine when called. How do I get around this issue? Thanks!
There is a workaround for this, if you can accept it.
Add the following to your Point class:
public static Point Clone(Point p)
{
return new Point(p);
}
Then in the code that is currently failing to compile, do this instead:
Point p = new Point(0, 0, 0);
Point q = Point.Clone(p);
(Of course, you don't have to call the method Clone() - call it Copy or CopyCtor or whatever you like.)
As to why the compiler insists that you must include a reference to an assembly defining types that you're not even using, see this answer.
Also see this question.

Unsafe structs in C#

I wanted to try c#'s unsafe 'feature' by creating simple structs (Vector, Particle).
SITUATION
I have this 2 structs and want to inject position and velocity vectors into my Particle struct.
As a test I wanted to print out position's X value, but somehow I'm getting random values.
I have the following code here
Vector
public readonly struct Vector
{
public int X { get; }
public int Y { get; }
public Vector(int x, int y)
{
X = x;
Y = y;
}
}
Particle
public unsafe struct Particle
{
private Vector* mPosition;
private Vector* mVelocity;
public Particle(Vector position, Vector velocity = default)
{
mPosition = &position; // here is x 10
mVelocity = &velocity;
}
public int GetPosX()
{
return mPosition->X; // but here not
}
}
Program
public class Program
{
private static void Main(string[] args)
{
var pos = new Vector(10, 5);
var obj = new Particle(pos);
Console.WriteLine(obj.GetPosX()); // prints random value
}
}
PROBLEM
It prints a random value instead of 10.
class Program {
static void Main (string [ ] args) {
unsafe {
Vector pos = new Vector(10, 5);
Particle obj = new Particle(&pos);
// &pos is at position 0xabcdef00 here.
// obj.mPosition has a different value here. It points to a different address? Or am I misunderstanding something
Console.WriteLine(obj.GetPosX( ));
}
}
}
public struct Vector {
public int X;
public int Y;
public Vector (int x, int y) {
X = x;
Y = y;
}
}
public unsafe struct Particle {
private Vector* mPosition;
public Particle (Vector *position) {
mPosition = position; // here is x 10
}
public int GetPosX ( ) {
return mPosition->X; // still 10 here
}
}
This works for me.
Please ... do not ask me why it does. You will notice that I didn't change that much. Just calling Particle with *pos instead of pos. For some reason that fixes the problem. You have to wrap the code with unsafe then and change the constructor for Particle obviously.
I could speculate about why it works, but I'd rather not. Maybe the pointer changes when you pass pos as a parameter for some reason?
You could not take the ref with right value.
Create a variable like int posX = 10;
And you can take the reference with variable. You take the compile time reference and read the runtime reference.
Don't use pointers without fixed. C# stack performance ise very good. You dont need this.
Usually pointers use with linking (C/Cpp dynamic library linking etc). If you have large structs (30 bytes and greater) then you can use the ref parameter tag.

Calling a parent class from a subclass

class experiment
{
int xCoord = 0;
int yCoord = 0;
public experiment(int x, int y) {
this.xCoord = x;
this.yCoord = y;
}
}
class result :experiment{
int zCoord = 0;
public result(int z) : base(x,y)
{
this.zCoord = z;
}
}
Can anyone help me solve this simple problem. I'm having an error base(x,y) it says the name 'x' does not exists in the current context and also goes for the y.
x and y are local fields to class experiment they are not visible in inherited class, you may call the base constructor with default values like:
public result(int z) : base(0,0)
Also please follow General Naming Conventions from Microsoft, so the class names begins with upper case character.
EDIT:
It would be better if your child class has a constructor to receive parameter x and y, and the it calls the base class constructor with those values like:
public result(int x, int y, int z) : base(x,y)
{
this.zCoord = z;
}
There is no x,y in constructor of result class.
You pass to your constructor z but tell your base constructor to recieve x and y. Though there are no x and y at that time.
Try this:
public result(int z, int x, int y) : base(x,y)
{
this.zCoord = z;
}
Or set fix values (no variables):
public result(int z) : base(0, 0)
{
this.zCoord = z;
}

Categories

Resources