generics类型的隐式运算符

使用隐式运算符有什么问题,如下所示:

//linqpad c# program example void Main() { var testObject = new MyClass() { Value = 1 }; var add = 10 + testObject; //implicit conversion to int here add.Dump(); // 11 } class MyClass { public T Value { get; set; } public static implicit operator T (MyClass myClassToConvert) { return myClassToConvert.Value; } } 

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

在我的实际代码中,我考虑将此作为数据抽象层的一部分,因此我可以返回包含描述底层数据的信息的对象,但允许逻辑代码在需要知道的所有内容时将其视为值类型是值,同时保持一切美观,并与generics类型安全。

如果满足以下所有条件:

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

  • 隐式运算符永远不会抛出(甚至不是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来源!

这是一个伟大的模式。 请记住,为了将其用作T类型的变量,您必须将其显式地转换为T ,或者将其分配给T类型的变量。 演员表将自动发生在方法调用和其他事物(例如你的加法示例)中。

没有赋值的隐式转换?