【问题标题】:Is there a workaround for overloading the assignment operator in C#?是否有在 C# 中重载赋值运算符的解决方法?
【发布时间】:2010-09-22 12:04:15
【问题描述】:

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

我正在为具有非常大数字的算术运算做一个自定义 Number 类,我希望它具有内置数字类型(如 int、decimal 等)的外观。我重载了算术运算符,但赋值仍然存在...

这是一个例子:

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

是否有解决该问题的方法?

【问题讨论】:

  • 解释问题(为什么需要它)。
  • 对不起,也许我应该更具体一些。我正在为具有非常大数字的算术运算做一个自定义 Number 类,我希望它具有内置数字类型(如 int、decimal 等)的外观。我重载了算术运算符,但是任务仍然...
  • 谢谢 - 我已将您的评论添加到问题本身。
  • 这里是一个例子: Number a = new Number(55);数字 b = a;我希望它复制值,而不是引用。
  • 查看 DateTime 和 TimeSpan。那里有很多方法。如果它实际上是一个原子值,那么它可能应该是一个结构。数字几乎总是属于这一类。

标签: c# operator-overloading


【解决方案1】:

这是一个适合我自己的解决方案:

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

代码中的其他地方:

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

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

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

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

      Foo x = "whatever";
      

      【讨论】:

      • 酷,这回答了一个我不想问的问题;)
      • 只有在您尝试将一种类型分配给另一种类型时才有效?毕竟,这是一个隐含的演员表。如果您想将Number 分配给Number,我认为这不会有帮助。
      • @Jonathan Wood - 这正是我想要的!非常感谢!
      • @drew-noakes:如果你想将 Number 赋值给 Number,并且 Number 是一个结构体,那么无论如何你都可以使用默认的赋值运算符获得想要的效果:Assign by value。
      • @Nilzor,在这种情况下,您会得到您所说的值的副本,但 OP 想用自己的代码以某种方式控制该过程。除非您在两种类型之间进行调整,否则我认为这是不可能的。所以它与你在 C++ 中可以做的略有不同。
      【解决方案4】:

      较早的帖子建议这样做:

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

      我尝试过这种方法...但要使其发挥作用,您需要这样做:

      public static 隐式运算符 Foo(Foo original) { }

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

      【讨论】:

      • "implicit 关键字用于声明一个隐式的用户定义类型转换运算符。使用它来启用用户定义类型和另一种类型之间的隐式转换,...​​" - MSDN
      【解决方案5】:

      我仍然不清楚你是否真的需要这个。要么:

      • 您的 Number 类型应该是一个结构(这是可能的 - 数字是最常见的结构示例)。请注意,您希望类型表现的所有类型(int、decimal 等)都是结构。

      或:

      • 您的 Number 类型应该是不可变的,使每个突变操作都返回一个新实例,在这种情况下,您无论如何都不需要在分配时复制数据。 (事实上​​,你的类型应该是不可变的,不管它是不是结构体。可变结构体是邪恶的,数字当然不应该是可变引用类型。)

      【讨论】:

      • 是的,也许结构体的想法很好。而且我喜欢不变性选项-在另一个答案中提出了建议。谢谢,我会试试你的建议。
      • 可变结构可能是邪恶的,但 C# 团队认为它们可以用于枚举数。我认为把它作为一般规则说更正确。
      • 可变性不是邪恶的,如果你能阻止对象共享。这可以通过实现需要某种形式的赋值重载的线性类型来完成。 en.wikipedia.org/wiki/Linear_type_system.
      【解决方案6】:

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

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

      【讨论】:

        【解决方案7】:

        你将无法以 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 */
        

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

        解决方法很简单:

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

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

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

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

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

        【讨论】:

        • 也许我可以那样做。但我的意思是 - 一种解决方法,它给我赋值运算符重载的真实外观,所以我可以从字面上说: MyType a = new MyType();我的类型 b = 新的我的类型(); a = b;它执行一些自定义分配逻辑。
        • 对它为什么不起作用的描述很准确。不过,正如您所建议的,Self 财产的想法并不是那么好,
        • "在 C++ 中,a = b 改变了 a 的内容。" - 那不完全正确。这取决于 a 和 b 是否是指针。 a=b 可以指向 b 或者它可以调用你的 = 重载并将内容复制到 a。
        • @MickyDuncan Eh.. 这是完全正确的。如果 a 和 b 是指针,你认为它们的内容是什么?当内容是指针时,“仅复制指针”与“复制内容”有何不同?
        • @TheDag c++ = 赋值既可以使指针指向同一个对象,也可以根据变量类型更改内容。一个没有确定我们只是在谈论指针
        猜你喜欢
        • 2016-05-13
        • 1970-01-01
        • 2013-02-27
        • 2012-08-17
        • 2013-03-30
        • 2016-08-30
        • 1970-01-01
        • 1970-01-01
        • 2012-04-22
        相关资源
        最近更新 更多