泛型类型的隐式运算符

时间:2010-09-29 15:32:18

标签: c# generics implicit-conversion

使用隐式运算符是否有任何问题:

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

我原以为我可以把这个对象的实例视为一种价值类型,但看到我从未见过这样的例子,我想也许有一个理由做有人可以指出这样的事情吗?

在我的实际代码中,我考虑将此作为数据抽象层的一部分,以便我可以返回包含描述底层数据的信息的对象,但允许逻辑代码在需要时将其视为值类型了解它的价值,同时保持它的美观,并使用泛型类型安全。

2 个答案:

答案 0 :(得分:10)

如果满足以下所有条件:

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

  • 隐式运算符永不抛出(甚至不是T!)

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

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

例如,请考虑null没有隐式转换为T?(其中T当然是值类型)。如果存在这样的隐式运算符,则在T为空时必须抛出,因为没有明显的值将T?转换为 any 值类型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); 的来源!

答案 1 :(得分:1)

这是一个很棒的模式。请记住,为了将其用作T类型的变量,您必须将其明确地转换为T,或者将其分配给T类型的变量。演员表将在方法调用和其他事物(例如您的添加示例)中自动进行,并采用T

Implicit conversion without assignment?