使用隐式运算符是否有任何问题:
//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;
}
}
我原以为我可以把这个对象的实例视为一种价值类型,但看到我从未见过这样的例子,我想也许有一个理由不做有人可以指出这样的事情吗?
在我的实际代码中,我考虑将此作为数据抽象层的一部分,以便我可以返回包含描述底层数据的信息的对象,但允许逻辑代码在需要时将其视为值类型了解它的价值,同时保持它的美观,并使用泛型类型安全。
答案 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
。