是否有在 C# 中重载赋值运算符的解决方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/292676/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 21:57:08  来源:igfitidea点击:

Is there a workaround for overloading the assignment operator in C#?

c#operator-overloading

提问by

Unlike C++, in C# you can't overload the assignment operator.

与 C++ 不同,在 C# 中不能重载赋值运算符。

I'm doing a custom Number class for arithmetic operations with very large numbers and I want it to have the look-and-feel of the built-in numerical types like int, decimal, etc. I've overloaded the arithmetic operators, but the assignment remains...

我正在为非常大的数字进行算术运算的自定义 Number 类,我希望它具有内置数字类型(如 int、decimal 等)的外观。我已经重载了算术运算符,但是任务仍然...

Here's an example:

下面是一个例子:

Number a = new Number(55); 
Number b = a; //I want to copy the value, not the reference

Is there a workaround for that issue?

有解决这个问题的方法吗?

采纳答案by Jon Skeet

It's still not at all clear to me that you really need this. Either:

我仍然完全不清楚您是否真的需要这个。任何一个:

  • Your Number type should be a struct (which is probable - numbers are the most common example of structs). Note that all the types you want your type to act like (int, decimal etc) are structs.
  • 您的 Number 类型应该是一个结构体(这很可能 - 数字是最常见的结构体示例)。请注意,您希望类型表现的所有类型(int、decimal 等)都是结构体。

or:

或者:

  • Your Number type should be immutable, making every mutation operation return a new instance, in which case you don't need the data to be copied on assignment anyway. (In fact, your type should be immutable whether or not it's a struct. Mutable structs are evil, and a number certainly shouldn't be a mutable reference type.)
  • 您的 Number 类型应该是不可变的,使每个突变操作都返回一个新实例,在这种情况下,无论如何您都不需要在赋值时复制数据。(事实上​​,你的类型应该是不可变的,无论它是否是一个结构体。可变结构体是邪恶的,数字当然不应该是一个可变引用类型。)

回答by Johannes Schaub - litb

You won't be able to work around it having the C++ look, since a = b; has other semantics in C++ than in C#. In C#, a = b; makes a point to the same object like b. In C++, a = b changes the content of a. Both has their ups and downs. It's like you do

您将无法使用 C++ 外观来解决它,因为 a = b; 在 C++ 中比在 C# 中具有其他语义。在 C# 中,a = b; 指向与 b 一样的对象。在 C++ 中,a = b 改变了 a 的内容。两者都有其起起落落。就像你一样

MyType * a = new MyType();
MyType * b = new MyType(); 
a = b; /* only exchange pointers. will not change any content */

In C++ (it will lose the reference to the first object, and create a memory leak. But let's ignore that here). You cannot overload the assign operator in C++ for that either.

在 C++ 中(它会丢失对第一个对象的引用,并造成内存泄漏。但让我们在这里忽略它)。您也不能为此重载 C++ 中的赋值运算符。

The workaround is easy:

解决方法很简单:

MyType a = new MyType();
MyType b = new MyType();

// instead of a = b
a.Assign(b);

Disclaimer: I'm not a C# developer

免责声明:我不是 C# 开发人员

You could create a write-only-property like this. then do a.Self = b; above.

您可以像这样创建一个只写属性。然后做a.Self = b; 以上。

public MyType Self {
    set {
        /* copy content of value to this */
        this.Assign(value);
    }
}

Now, this is notgood. Since it violates the principle-of-least-surprise (POLS). One wouldn't expect a to change if one does a.Self = b;

现在,这是不是好。因为它违反了最小意外原则(POLS)。如果一个人做了 a.Self = b; 就不会期望 a 发生变化。

回答by Cristian Libardo

Instead of making a copy of the data when passing the reference you could make the class immutable. When the class is immutable having multiple references to it isn't a problem since it can't be changed.

您可以使类不可变,而不是在传递引用时复制数据。当类是不可变的时,对它的多个引用不是问题,因为它无法更改。

Operations that changes the data would of course return new instances.

更改数据的操作当然会返回新实例。

回答by Jon Skeet

you can use the 'implicit' keyword to create an overload for the assignment:

您可以使用“隐式”关键字为赋值创建重载:

Suppose you have a type like Foo, that you feel is implicitly convertable from a string. You would write the following static method in your Foo class:

假设你有一个像 Foo 这样的类型,你觉得它可以从字符串隐式转换。您将在 Foo 类中编写以下静态方法:

public static implicit operator Foo(string normalString)
{
    //write your code here to go from string to Foo and return the new Foo.
}

Having done that, you can then use the following in your code:

完成后,您可以在代码中使用以下内容:

Foo x = "whatever";

回答by DMC

An earlier post suggested this:

之前的一篇文章提出了这一点:

public static implicit operator Foo(string normalString) { }

公共静态隐式运算符 Foo(string normalString) { }

I tried this approach... but to make it work you need this:

我试过这种方法……但要让它工作,你需要这个:

public static implicit operator Foo(Foo original) { }

公共静态隐式运算符 Foo(Foo original) { }

and the compiler won't let you have an implicit conversion function from your exact type, nor from any base type of yourself. That makes sense since it would be a backdoor way of overriding the assignment operator, which C# doesn't want to allow.

并且编译器不会让您从您的确切类型或您自己的任何基类型获得隐式转换函数。这是有道理的,因为它是一种覆盖赋值运算符的后门方式,C# 不希望允许这种方式。

回答by TDot

Maybe what you're looking for can be solved using C# accessors.

也许您正在寻找的东西可以使用 C# 访问器来解决。

http://msdn.microsoft.com/en-us/library/aa287786(v=vs.71).aspx

http://msdn.microsoft.com/en-us/library/aa287786(v=vs.71).aspx

回答by ttrixas

Here is a solution that worked for myself :

这是一个对我有用的解决方案:

public class MyTestClass
{
   private int a;
   private string str;

   public MyTestClass()
   {
      a = 0;
      str = null;
   }

   public MyTestClass(int a, string str)
   {
      this.a = a;
      this.str = str;
   }

   public MyTestClass Clone
   {
      get
      {
         return new MyTestClass(this.a, this.str);
      }
   }
}

Somewhere else in the code :

代码中的其他地方:

MyTestClass test1 = new MyTestClass(5, "Cat");
MyTestClass test2 = test1.Clone;