Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何制作+;=操作员是否保留对象引用?_C#_Operators_Addition - Fatal编程技术网

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);