C# 如何制作+;=操作员是否保留对象引用?
比如说,我有一门课:C# 如何制作+;=操作员是否保留对象引用?,c#,operators,addition,C#,Operators,Addition,比如说,我有一门课: class M { public int val; 还有一个+操作符: public static M operator +(M a, M b) { M c = new M(); c.val = a.val + b.val; return c; } } 我有一个类对象的列表: List<M> ms = new List(); M obj = new M(); obj.val
class M
{
public int val;
还有一个+
操作符:
public static M operator +(M a, M b)
{
M c = new M();
c.val = a.val + b.val;
return c;
}
}
我有一个类对象的列表
:
List<M> ms = new List();
M obj = new M();
obj.val = 5;
ms.Add(obj);
我可以这样做:
ms[0] += addie;
它确实如我所期望的那样工作-列表中的值已更改。但是如果我想做的话
M fromList = ms[0];
fromList += addie;
由于明显的原因,它不会更改ms
中的值
但直觉上,我希望ms[0]
之后也会发生变化。实际上,我从列表中选取对象,然后用其他对象增加它的值。因此,由于在添加之前,我在fromList
中保留了对ms[0]
的引用,因此在执行之后,我仍然希望在fromList
中保留它
有什么方法可以做到这一点吗?你不应该期望ms[0]
改变。初始化后,fromList
根本不与ms
连接-fromList
和ms[0]
恰好具有相同的值,仅此而已正在返回一个新值(实际上应该是这样),因此您只需更改存储在fromList
中的值,该值完全独立于列表中的值。(请注意,此处的值是引用,而不是对象。)
不要试图改变这种行为——这是在做正确的事情。改变你的期望
如果确实希望列表的内容反映更改,则需要更改列表中的值以引用新对象,或者需要更改代码以改变现有对象,而不是创建新对象。如果采用后一种方法,则应而不是在操作员内执行此操作。相反,创建一个Add
方法,以便调用:
fromList.Add(addie);
很明显,这是一种变异操作,因此不会打破任何预期
就我个人而言,我会尝试使用不可变类型,并调整您的设计,使您不需要更改列表(或直接对列表进行操作)。您不应该期望ms[0]
更改。初始化后,fromList
根本不与ms
连接-fromList
和ms[0]
恰好具有相同的值,仅此而已正在返回一个新值(实际上应该是这样),因此您只需更改存储在fromList
中的值,该值完全独立于列表中的值。(请注意,此处的值是引用,而不是对象。)
不要试图改变这种行为——这是在做正确的事情。改变你的期望
如果确实希望列表的内容反映更改,则需要更改列表中的值以引用新对象,或者需要更改代码以改变现有对象,而不是创建新对象。如果采用后一种方法,则应而不是在操作员内执行此操作。相反,创建一个Add
方法,以便调用:
fromList.Add(addie);
很明显,这是一种变异操作,因此不会打破任何预期
就我个人而言,我会尝试使用不可变类型,并调整您的设计,使您不需要更改列表(或直接对列表进行操作)。尽量避免实现运算符。大多数情况下,这不值得费心,而且会使代码更加混乱。改为实现简单的添加/删除方法。此外,如果最终在对象中添加其他值,则扩展会更容易。通过使用运算符,您可以使用与整个对象相关的语义来作用于该对象的一部分。当与struct一起使用时,运算符通常更有意义。在实现与值类型类似的类型时,应该使用结构。尽量避免实现运算符。大多数情况下,这不值得费心,而且会使代码更加混乱。改为实现简单的添加/删除方法。此外,如果最终在对象中添加其他值,则扩展会更容易。通过使用运算符,您可以使用与整个对象相关的语义来作用于该对象的一部分。当与struct一起使用时,运算符通常更有意义。当实现应该像值类型一样工作的类型时,应该使用结构。您将可变行为与不可变行为混为一谈,我认为这是令人困惑的地方 对象是可变的(即,您可以更改其属性),并且当您为其属性指定值时,它的行为与您预期的一样 当您使用+运算符时,它的行为将改为不可变值。假设您有一个整数列表,并将整数读入变量。如果更改变量的值,则不会在列表中排除要更改的整数:
List<int> list = new List<int>() { 1, 2, 3};
int x = list[0];
// this will of cousre not change the content in the list:
x += 42;
编译器使用+运算符,如下所示:
M fromList = ms[0];
fromlist = fromList + addie;
表达式
fromlist+addie
返回对类的新实例的引用,该引用被分配给变量。这自然不会改变变量之前引用的对象。您将可变行为与不可变行为混为一谈,我认为这就是它变得混乱的原因
对象是可变的(即,您可以更改其属性),并且当您为其属性指定值时,它的行为与您预期的一样
当您使用+运算符时,它的行为将改为不可变值。假设您有一个整数列表,并将整数读入变量。如果更改变量的值,则不会在列表中排除要更改的整数:
List<int> list = new List<int>() { 1, 2, 3};
int x = list[0];
// this will of cousre not change the content in the list:
x += 42;
编译器使用+运算符,如下所示:
M fromList = ms[0];
fromlist = fromList + addie;
表达式
fromlist+addie
返回对类的新实例的引用,该引用被分配给变量。这自然不会改变变量以前引用的对象。 < P>复合赋值与简单算子之间的关系在C++中与C++完全不同。
在C#中,复合赋值运算符将
fromlist += addie;
fromlist = fromlist.op+(addie);
std::string operator[](int nIndex);
std::string& operator[](int nIndex);
list[3] = "hi";
std::string& oops = list[3];
public string this[int index]
{
get { /* return a string somehow */ }
set { /* do something with implicit 'value' param */ }
}
ms[0] += addie;
ms[0] = ms[0] + addie;
ms.SetAt(0, ms.GetAt(0) + addie);