Is there a workaround for overloading the assignme

2019-01-21 11:07发布

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

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...

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?

7条回答
我命由我不由天
2楼-- · 2019-01-21 11:22

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

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.

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

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

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

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

查看更多
戒情不戒烟
3楼-- · 2019-01-21 11:23

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:

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";
查看更多
三岁会撩人
4楼-- · 2019-01-21 11:26

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;
查看更多
Anthone
5楼-- · 2019-01-21 11:26

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

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

查看更多
仙女界的扛把子
6楼-- · 2019-01-21 11:29

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.

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.)
查看更多
Ridiculous、
7楼-- · 2019-01-21 11:29

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.

查看更多
登录 后发表回答