为什么隐式运算符必须是静态的?

时间:2018-08-31 09:24:21

标签: c#

我有一个名为FloatPlugIn的课程。我希望用户能够执行

之类的操作
FloatPlugIn x = new FloatPlugIn();
x.Minimum = -100;
x.Maximum = 100;

float y = 123;
x = y;

这就是为什么我决定在课堂上添加implicit operator

public static implicit operator FloatPlugIn(float p)
{
    return new FloatPlugIn() { Default = p };
}

问题是隐式运算符必须是静态的,这就是为什么在转换期间创建类的新实例的原因。结果,我失去了位于“旧”实例内部的所有信息。

是否可以解决该问题?我希望将float值应用于现有实例,而不是完全替换它。

3 个答案:

答案 0 :(得分:1)

我认为您不了解转换的作用-它不是强制转换-它必须创建一个新实例。仅在更新现有实例的情况下,使其变为非静态才有意义。

答案 1 :(得分:0)

在这种情况下,如果您使用x.Default = y;或创建一个采用如下浮点数的构造函数,则最好:

// Constructor
public FloatPlugIn(float p)
{
    Default = p;
}

用法:

float y = 123;
FloatPlugIn x = new FloatPlugIn(y);

答案 2 :(得分:0)

assignment operator的语义要求这种行为。实际上:

  

赋值运算符(=)将其右操作数的值存储在由其左操作数表示的存储位置,属性或索引器中,并返回该值作为其结果。操作数必须具有相同的类型(或者右侧操作数必须隐式转换为左侧操作数的类型。)

修改目标值并不是隐式转换运算符的目的-请注意,可能没有任何这样的目标值,例如如果您通过方法参数的值。

  

我希望将float值添加到现有实例中,而不是完全替换它。

如果您要添加 (在您的情况下,无论是哪种特定含义),请考虑覆盖加法+运算符,这反过来会影响{{3} }。但是,无论如何您都不会消除创建新的FloatPlugIn实例的情况。

请考虑在FloatPlugIn中使用以下方法,该方法将修改现有实例:

public void Add(float f)
{
    // do whatever 'addition' means in your case
}

然后+运算符应像这样工作:

public static FloatPlugIn operator +(FloatPlugIn a, float b)
{
    FloatPlugIn result = a.Clone(); // here Clone() denotes any custom method that creates a copy of that instance
    result.Add(b);
    return b;
}

在您的代码中,以下代码将起作用:

FloatPlugIn x = new FloatPlugIn();
x.Minimum = -100;
x.Maximum = 100;

float y = 123;
x += y; // a new instance is created, but the 'addition' logic is preserved

此外,在将值传递给方法调用的情况下,同样可以直观地工作:

ProcessMyFloatPlugin(x + 123.0f);

您会发现,由于操作员的缘故,创建一个FloatPlugIn的新实例是一个非常好的主意。否则,x的就地修改实际上是一个讨厌的副作用,任何其他开发人员都完全无法预料。请注意,如果您担心性能(避免动态内存分配),请考虑使用struct