Home > Enterprise >  Overloaded increment operator that's supposed to only return a temp object changes the original
Overloaded increment operator that's supposed to only return a temp object changes the original

Time:01-26

I'm currently going through a C# course (a bit too outdated and terminology-heavy one to boot), and one of the demos is supposed to teach us how to overload operators in a class. They make an array class and overload unary operators - and . They're both written the same way, creating a temp new array object in which every integer is either inverted or incremented, and then return the temp. However, as revealed by printing the array, the - operation doesn't change the original array, while the does. Why? The course doesn't explain anything in that regard and doesn't even tell what the desired output is. I don't even know if it's supposed to work this way or something has changed since the outdated time of this course's writing.

class DemoArray
    {
        int[] MyArray;
        public DemoArray(int size)
        {
            MyArray = new int[size];
        }
        public DemoArray(params int[] arr)
        {
            MyArray = new int[arr.Length];
            for (int i = 0; i < MyArray.Length; i  ) MyArray[i] = arr[i];
        }
        public int LengthArray
        {
            get { return MyArray.Length; }
        }
        public int this[int i]
        {
            get
            {
                if (i < 0 || i >= MyArray.Length)
                    throw new Exception("out of array bounds");
                return MyArray[i];
            }
            set
            {
                if (i < 0 || i >= MyArray.Length)
                    throw new Exception("out of array bounds");
                else MyArray[i] = value;
            }
        }

        public static DemoArray operator -(DemoArray x)
        {
            DemoArray temp = new DemoArray(x.LengthArray);
            for (int i = 0; i < x.LengthArray;   i)
                temp[i] = -x[i];
            return temp;
        }
        public static DemoArray operator   (DemoArray x)
        {
            DemoArray temp = new DemoArray(x.LengthArray);
            for (int i = 0; i < x.LengthArray;   i)
                temp[i] = x[i]   1;
            return temp;
        }
        public void Print(string name)
        {
            Console.WriteLine(name   ": ");
            for (int i = 0; i < MyArray.Length; i  )
                Console.Write(MyArray[i]   " ");
            Console.WriteLine();
        }
}
    class Program
    {
        static void Main()
        {
            try
            {
                DemoArray Mas = new DemoArray(1, -4, 3, -5, 0);
                Mas.Print("Original array");
                Console.WriteLine("\nUnary inversion");
                DemoArray newMas = -Mas;
                Mas.Print("Array Mas");
                newMas.Print("Array newMas");
                Console.WriteLine("\nPrefix increment");
                DemoArray Mas1 =   Mas;
                Mas.Print("Array Mas");
                Mas1.Print("Array Mas1=  Mas");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }

And the output displays:

Original array:
1 -4 3 -5 0

Unary inversion
Array Mas:
1 -4 3 -5 0
Array newMas:
-1 4 -3 5 0

Prefix increment
Array Mas:
2 -3 4 -4 1
Array Mas1=  Mas:
2 -3 4 -4 1

So, why did the original array Mas get modified by the overloaded increment again? Btw, I've tried overloading the operator to inverse integers and the - operator to increment them, and the - operator still doesn't change the original array, while the operator does.

CodePudding user response:

C# automatically constructs increment, decrement, and compound assignment operators by calling the overloaded operator function and assigning the result.

You can read the rules in C# Language Specification section 11.7.14 Postfix increment and decrement operators

In particular, you get = for free when defining operator , and you get both prefix increment and postfix increment when defining operator , and that works because C# controls when the assignment happens (so it can choose a different ordering for prefix and postfix).

There's even a note in section 14.10.2 Unary operators

Unlike in C , this method should not modify the value of its operand directly as this would violate the standard semantics of the postfix increment operator.

(C requires the programmer to provide separate functions for prefix-increment and postfix-increment)


All of that said, your conclusion that Mas changed the original array is incorrect. The original array is still out there, unchanged (until the garbage collector finds it). But the variable Mas is pointing to the new array, same as Mas1 is.

Try this snippet for proof:

DemoArray Mas = new DemoArray(1, -4, 3, -5, 0);
DemoArray Old = Mas;
DemoArray Mas1 =   Mas;
Mas.Print("Array Mas");
Mas1.Print("Array Mas1=  Mas");
Old.Print("Array Old");
Console.WriteLine(ReferenceEquals(Mas, Old)); // false
Console.WriteLine(ReferenceEquals(Mas, Mas1)); // true
  •  Tags:  
  • Related