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
类型的变量。 演员表将自动发生在方法调用和其他事物(例如你的加法示例)中。
没有赋值的隐式转换?