应该只 return 临时对象更改原始对象的重载增量运算符。为什么?
Overloaded increment operator that's supposed to only return a temp object changes the original object. Why?
我目前正在学习 C# 课程(有点太过时且术语太多,无法启动),其中一个演示应该教我们如何在 class 中重载运算符。他们创建一个数组 class 并重载一元运算符 - 和 ++。它们的编写方式相同,创建一个临时新数组对象,其中每个整数都被反转或递增,然后 return 临时。但是,正如打印数组所揭示的那样,- 操作不会更改原始数组,而 ++ 会。为什么?该课程在这方面没有解释任何内容,甚至没有说明所需的输出是什么。我什至不知道它是否应该以这种方式工作,或者自本课程写作的过时时间以来发生了一些变化。
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);
}
}
}
并且输出显示:
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
那么,为什么原来的数组Mas又被重载的增量修改了呢?顺便说一句,我已经尝试过重载 ++ 运算符 来反转 整数和 - 运算符 来增加 它们,而 - 运算符仍然没有更改原始数组,而 ++ 运算符。
C#通过调用重载运算符函数并对结果进行赋值,自动构造递增、递减和复合赋值运算符。
您可以阅读 C# 语言规范中的规则 section 11.7.14 Postfix increment and decrement operators
特别是,您在定义 operator+
时免费获得 +=
,并且在定义 operator++
时同时获得前缀增量和后缀增量,这是有效的,因为 C# 控制何时分配发生(因此它可以为前缀和后缀选择不同的顺序)。
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++要求程序员为prefix-increment和postfix-increment提供单独的函数)
综上所述,您认为 ++Mas
更改了原始数组的结论是不正确的。原始数组仍然在那里,没有变化(直到垃圾收集器找到它)。但是变量 Mas
指向新数组,与 Mas1
相同。
试试这个片段来证明:
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
我目前正在学习 C# 课程(有点太过时且术语太多,无法启动),其中一个演示应该教我们如何在 class 中重载运算符。他们创建一个数组 class 并重载一元运算符 - 和 ++。它们的编写方式相同,创建一个临时新数组对象,其中每个整数都被反转或递增,然后 return 临时。但是,正如打印数组所揭示的那样,- 操作不会更改原始数组,而 ++ 会。为什么?该课程在这方面没有解释任何内容,甚至没有说明所需的输出是什么。我什至不知道它是否应该以这种方式工作,或者自本课程写作的过时时间以来发生了一些变化。
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);
}
}
}
并且输出显示:
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
那么,为什么原来的数组Mas又被重载的增量修改了呢?顺便说一句,我已经尝试过重载 ++ 运算符 来反转 整数和 - 运算符 来增加 它们,而 - 运算符仍然没有更改原始数组,而 ++ 运算符。
C#通过调用重载运算符函数并对结果进行赋值,自动构造递增、递减和复合赋值运算符。
您可以阅读 C# 语言规范中的规则 section 11.7.14 Postfix increment and decrement operators
特别是,您在定义 operator+
时免费获得 +=
,并且在定义 operator++
时同时获得前缀增量和后缀增量,这是有效的,因为 C# 控制何时分配发生(因此它可以为前缀和后缀选择不同的顺序)。
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++要求程序员为prefix-increment和postfix-increment提供单独的函数)
综上所述,您认为 ++Mas
更改了原始数组的结论是不正确的。原始数组仍然在那里,没有变化(直到垃圾收集器找到它)。但是变量 Mas
指向新数组,与 Mas1
相同。
试试这个片段来证明:
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