9

使用如下隐式运算符有什么问题吗:

//linqpad c# program example
void Main()
{
    var testObject = new MyClass<int>() { Value = 1 };

    var add = 10 + testObject; //implicit conversion to int here
    add.Dump(); // 11
}

class MyClass<T>
{
    public T Value { get; set; }
    public static implicit operator T (MyClass<T> myClassToConvert)
    {
        return myClassToConvert.Value;
    }
}

我在想我可以以这种方式将对象的实例视为值类型,但是看到我从未见过这样的例子,我想也许有理由不做这样的事情,有人可以指出?

在我的实际代码中,我正在考虑将其作为数据抽象层的一部分,以便我可以返回带有描述底层数据的信息的对象,但允许逻辑代码在它需要知道的所有内容时将其视为值类型是值,同时使用泛型保持良好和类型安全。

4

2 回答 2

10

如果以下所有条件都为真:

  • 您的类型的所有可能值MyClass<T>(包括null如果它不是值类型!)映射到的有效值T

  • 隐式运算符从不抛出(甚至 for null!)

  • 隐式转换具有语义意义,不会让客户端程序员感到困惑

那么这并没有错。当然,你可以做这三件事中的任何一件,但这将是糟糕的设计。特别是,抛出的隐式运算符可能很难调试,因为调用它的地方并没有说它正在被调用。

例如,考虑T?没有隐式转换为T(其中T当然是值类型)。如果有这样一个隐式运算符,它必须在T?为 null 时抛出,因为没有明显的值可以转换null任何值类型都有意义T


让我举一个例子,我在调试隐式运算符抛出的问题时遇到了麻烦:

public string Foo()
{
    return some_condition ? GetSomething() : null;
}

在这里,GetSomething返回了一些我写的类型,它有一个用户定义的隐式转换为string. 我绝对确定GetSomething永远不会回来null,但我得到了一个NullReferenceException!为什么?因为上面的代码等价于

return some_condition ? (string)GetSomething() : (string)null;

但要

return (string)(some_condition ? GetSomething() : (Something)null);

现在你可以看到它是null从哪里来的!

于 2010-09-29T15:35:54.803 回答
1

这是一个很棒的模式。请记住,为了将其用作类型变量T,您必须将其显式强制转换为T,或将其分配给类型变量T。转换将在方法调用和其他需要T.

没有赋值的隐式转换?

于 2010-09-29T15:35:55.817 回答