Public Properties in structures

a_anis3000
a_anis3000 used Ask the Experts™
on
In the code below I get the following error message at line 53

line2.cs(53,7): error CS1612: Cannot modify the return value of 'line.starting'
        because it is not a variable
line2.cs(54,7): error CS1612: Cannot modify the return value of 'line.starting'
        because it is not a variable
line2.cs(55,7): error CS1612: Cannot modify the return value of 'line.ending'
        because it is not a variable
line2.cs(56,7): error CS1612: Cannot modify the return value of 'line.ending'
        because it is not a variable

I double checked the code several times and having hard figuring out why it won't let me assign values to myLine.starting.x , though the members access type is private they have public properties so they should be accessible
//  line2.cs - Adding methods to a structure. 
//--------------------------------------------------------------------

struct point
{
    private int point_x;
    private int point_y;

    public int x
    {
        get { return point_x; }
        set { point_x = value; }
    }
    public int y
    {
        get { return point_y; }
        set { point_y = value; }
    }
}

struct line
{

    private point line_starting;
    private point line_ending;

    public point starting
    {
        get { return line_starting; }
        set { line_starting = value; }
    }
    public point ending
    {
        get { return line_ending; }
        set { line_ending = value; }
    }

    public double length()
    {
       double len = 0;
       len = System.Math.Sqrt( (ending.x - starting.x)*(ending.x - starting.x) + 
                               (ending.y - starting.y)*(ending.y - starting.y));
       return len;
    }
}

class lineApp
{
   public static void Main()
   {
      line myLine;
      
      myLine.starting.x = 1;
      myLine.starting.y = 4;
      myLine.ending.x = 10;
      myLine.ending.y = 11;

      System.Console.WriteLine("Point 1: ({0},{1})",
                                myLine.starting.x, myLine.starting.y);
      System.Console.WriteLine("Point 2: ({0},{1})",
                                myLine.ending.x, myLine.ending.y);
      System.Console.WriteLine("Length of line from Point 1 to Point 2: {0}",
                                myLine.length());
   }
}

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Just change struct to class.
> line2.cs(53,7): error CS1612: Cannot modify the return value of 'line.starting'
        because it is not a variable

The property construct is returning a COPY of the point data as opposed to a reference. So, if you were to change the value of say "x", nothing would actually happen to the original object.

myLine.starting.x = 1;

Is similar to:

point test = myLine.starting;
test.x = 1;

This doesn't affect the original line object because "struct" objects are always copied on assignment; whereas a "class" object is passed by reference.

Depending upon your requirements you could either follow Sinistra_D32's advice and use a class instead of a struct (so that references are used instead of objects). In some scenarios it is desirable to use custom setter functions (that would exist within the line object, not the point).

For example:

myLine.setStartingLocation(1, 4);
myLine.setEndingLocation(10, 11);

or even:

myLine.setLocation(1, 4, 10, 11);
My advice is to put a constructor in the "point" class like
struct point
{
    private int point_x;
    private int point_y;

    public point(int X, int Y)
        {
            point_x = X;
            point_y = Y;
        }
       ...
       ...
       ...
}
then in the code,
instead of the lines 53 to 56 which are generating the errors, replace them with the following.
---------------------------------
            line myLine=new line();
            myLine.starting=new point(1,4);
            myLine.ending = new point(10, 11);
---------------------------------

There you go.

Regarding the explanation about why it is causing the errors, refer the following link.

http://www.albahari.com/valuevsreftypes.aspx

with best regards.
Bootstrap 4: Exploring New Features

Learn how to use and navigate the new features included in Bootstrap 4, the most popular HTML, CSS, and JavaScript framework for developing responsive, mobile-first websites.

try this:
struct point
    {
        public int X { get; set; }
        public int Y { get; set; }

        public point(int x, int y) : this()
        {
            X = x;
            Y = y;
        }        
    }

    struct line
    {
        public point starting   { get; set; }        
        public point ending     { get; set; }

        public double length()
        {
            double len = 0;
            len = System.Math.Sqrt((ending.X - starting.X) * (ending.X - starting.X) +
                                    (ending.Y - starting.Y) * (ending.Y - starting.Y));
            return len;
        }
    }

    class lineApp
    {
        public static void Main()
        {
            line myLine = new line();

            myLine.starting = new point(1, 4);
            myLine.ending = new point(10, 11);

            System.Console.WriteLine("Point 1: ({0},{1})",
                                      myLine.starting.X, myLine.starting.Y);
            System.Console.WriteLine("Point 2: ({0},{1})",
                                      myLine.ending.X, myLine.ending.Y);
            System.Console.WriteLine("Length of line from Point 1 to Point 2: {0}",
                                      myLine.length());
        }
    }

Open in new window

is there any special reason you are using structs? a class would be a better solution unless you are working with older technology.

Author

Commented:
well normally I would use classes most of the time, but as I am learning C# I recently ran into the structures topic and want to fully grasp the difference between them and classes since they are so similar, particularly in terms of being value and reference type, thats why I am trying to use them instead of classes and see through trial and error the difference

Author

Commented:
>>The property construct is returning a COPY of the point data as opposed to a reference. So, if you were to change the value of say "x", nothing would actually happen to the original object.<<

Ok..... so its something to do with by-reference and by-value... but I don't think I have fully digested the idea yet. I tried repeating the idea in the code below. I was expecting an error at the line circle.Radius = 10; but for some reason it compiled and ran

using System;

struct Circle
{
    private double radius;
    public double Radius
    {
        get { return radius; }
        set { radius = value; }
    }

    public double circumference()
    {
        return 2 * Math.PI * radius;
    }

    public double area()
    {
        return Math.PI * radius * radius;
    }
}

class Program
{
    public static void Main()
    {
        Circle circle = new Circle();
        circle.Radius = 10;

        Console.WriteLine(circle.circumference());
        Console.WriteLine(circle.area());
    }
}

Open in new window

Hi a_anis3000,
When you use just a single structure, then it works fine as in your Circle struct. But in your question you are attempting to declare a variable of type point (struct) in a line (struct). In this case the reference vs value....ie., a heap vs stack plays a role. It is well explained at the following link.

http://www.albahari.com/valuevsreftypes.aspx

Did you go thru my previous comment?. Did it work for you?

Author

Commented:
yes all of the suggested solutions work fine. I already read your article habeeballah, it explained the reference and value type well. What I am trying to do now is apply what I learned from it in some code like the circle one I just did, but it looks like I got some misunderstanding

Author

Commented:
>>is there any special reason you are using structs? a class would be a better solution unless you are working with older technology.<<

one more thing before closing the question, while it won't hurt to learn about struct I was wondering if in practice I would be using classes most of the time. Won't I? Apart from struct being value type what advantage do they have over classes that I should use them instead. Do they offer better performance for instance?
Structures will offer better performance, but poorer extendability.

There are plenty things you can not do in a structure that you can in a class.

Structures are smaller (compiled) and should be used for - yes, - you guessed it ! structures.!!!

This is a type of "class" that only stores data but is not really functional.

ie:

public class abc
{
    public int id {get;set;}
    public string s1 {get;set;}
    public string s2 {get;set;}
    public string s3 {get;set;}
    public string s4 {get;set;}
...
etc ...
}

this should be a structure - as that is exactly what is is :) - it is a structural representation of something else (possibly a database table)
It really depends upon what you are designing. Most of the time you will be working with classes, but there are times that you need structs; especially when dealing with raw API calls.

Struct's are great when there is not a large amount of data and can be used to avoid inadvertently altering the values of previous instances (for example, if a value is parsed into a function).

Classes should be used when there is a large amount of data to avoid using lots of memory and hitting serious performance problems (parsing by reference is faster than allocating and copying to a new object). It is important to note that if the properties of a class instance are changed, the change will be apparent to ALL instances of that reference.
The following points tells you what are structs and why are they made(kept for our sake) for:

*   A C# structure is a value type and the objects of a structure are created on the stack. Because of this reason, there will be no involvement of the garbage collector and hence damn fast in the performance.

*   A structure in C# is simply a composite data type consisting of a number of elements of other types.

*   A structure in C# can contain fields, methods, constants, constructors, properties, indexers, operators and even other structure types.

* structs are mainly useful Whenever you have a need for a type that will be used often and is mostly just a piece of data and no functionality is involved. As per the most famous definition from Microsoft, "Structures are generally used for small objects that contain few data members with a fixed size of 16 bytes or less".

-----------------
Note : I said above that the structs are kept for our sake because if you observe the following points, you will get doubts that why couldn't the makers of C#/.Net let the structs to use the full features of the classes. Then if they would have done it, then who else in the world would like to use the classes. So there must me some drawbacks in the data structures of olden days. Here are those few points that degrades the structs and hence encourage us to use classes.
-----------------

*   In C#, every value type such as int, char, long and so on implicitly has a public parameter less default constructor. So it is not possible for a struct type to contain an explicit declaration of a parameter less constructor however there is no restriction to have a parameterful constructor. Therefore you an error if you attempt like
   
    struct point
    {
        private int point_x;
        private int point_y;
        public point()
        {
            point_x = 0;
            point_y = 0;
        }
    }

* You cannot derive any type from a struct (sealed by default). Also you cannot derive any struct from the class. Only thing you can do with struct in relation to the inheritance is that you can implement the interfaces.

* You cannot have instance field initializer in the structs as the following leads to an error whereas for a class can have an instance field initializer.
    struct point
    {
       private int point_x=10;
       ....
       ....
    }

* Self reference to a struct is illegal because a struct in C# is a value type. So the following leads to an error.

struct point
{
   internal point pointInpoint;
}


So finally, to make your code more understandable on the above concepts, I have converted just the "point" struct into a class without any other change. However the line struct remains as it is except with a one argument constructor and as described under.


class point
{
   private int point_x;
   private int point_y;

   public int x
   {
      get { return point_x; }
      set { point_x = value; }
   }
   public int y
   {
       get { return point_y; }
       set { point_y = value; }
   }
}

struct line
{
    private point line_starting;
    private point line_ending;
 // you can't create above point objects as the instance field initialization is banned in structs.
 // parameter fake is just for the sake of struct's STRINGENT rules and it is not for use.
    public line(int fake)
    {
        line_starting = new point();
        line_ending = new point();
    }

    public point starting
    {
        get { return line_starting; }
        set { line_starting = value; }
    }

    public point ending
    {
        get { return line_ending; }
        set { line_ending = value; }
    }
    public double length()
    {
        double len = 0;
        len = System.Math.Sqrt((ending.x - starting.x) * (ending.x - starting.x) +
                                (ending.y - starting.y) * (ending.y - starting.y));
        return len;
    }
}


then use the above data structures as follows:

    point startpoint = new point();
    point endpoint = new point();
    line myLine = new line(0);

now you can do the following without any problem because C# allows you to do it with the classes and not structures:

    myLine.starting.x = 1;
    myLine.starting.y = 4;
    myLine.ending.x = 10;
    myLine.ending.y = 11;

    System.Console.WriteLine("Point 1: ({0},{1})",
                          myLine.starting.x, myLine.starting.y);
    System.Console.WriteLine("Point 2: ({0},{1})",
                          myLine.ending.x, myLine.ending.y);
    System.Console.WriteLine("Length of line from Point 1 to Point 2: {0}",
                          myLine.length());


Hope this removes your doubts about the degraded power of the structs.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial