繁体   English   中英

如何确保显式运算符在转换 null 时抛出异常? (不可为空)

[英]How to make sure the explicit operator throws the exception when converting null? (not nullable)

我在MyVO类上有一个显式运算符,它应该是不可为空的。

public class MyVO : ValueObject<MyVO>
{
    public string Value { get; } // Should never be null

    private MyVO(string v) => Value = v;

    public static explicit operator MyVO(string vo)
    {
        if (string.IsNullOrWhiteSpace(vo)) throw new Exception('...');
        return new MyVO(vo);
    }

但是, (MyVO)null不会引发异常。 该方法的主体将不会运行。

var myVO = (MyVO)null; // myVO will have the null value

如何确保它不为空?

如何确保它不为空?

“它”我假设您的意思是“从nullMyVO ”。 如果这不是您的意思,请澄清问题。

你不能。

C# 的一个重要规则是用户定义的转换在与内置转换冲突时永远不会“获胜” null转换为任何类类型都是合法的,因此MyVO对表达式nullMyVO始终导致 null 引用。 如果内置转换有效,编译器甚至不会考虑用户定义的转换。 (相信我;我写了那个代码!)

正如 D Stanley 的回答正确指出的那样,如果nullstring类型的任何表达式的,则调用用户定义的转换; 没有从stringMyVO内置转换,因此编译器会查找适用的用户定义转换并找到一个。

因为当你做你正在做的事情时会很痛,你应该停止做你正在做的事情。 显式转换可能不是实现所需行为的正确方法。

我想我的问题应该是如何使MyVO不可为空。

升级到 C# 8。C# 8 支持对引用类型进行不可为空的注释。

请注意,不可为空的注释应该被正确地视为annotation 类型系统不保证用不可为空的注释注释的变量的值永远不会被观察到为空。 相反,它会尽最大努力在代码看起来有误时向您发出警告。


在我们查看您的代码时,我注意到您正在使用ValueObject<T> ,我假设您是从类似的东西中获得的

https://enterprisecraftsmanship.com/posts/value-object-better-implementation/

让我借此机会提醒您,使用这种模式存在缺陷; 认为希望被应用于约束T不是适用于约束T 我们经常看到这样的事情:

abstract class V<T> where T : V<T>
{
  public void M(T t) { ... }  // M must take an instance of its own type
}

如果我们有class Banana : V<Banana>那么Banana.M将一个Banana作为它的参数,这就是我们想要的。 但是现在假设我们有class Giraffe : V<Banana> 在这种情况下, Giraffe.M不带长颈鹿; 它需要一根香蕉,尽管GiraffeBanana根本没有关系。

约束并不意味着M始终把自己的类的实例。 如果您尝试在 C# 中使用这种约束构造泛型类型,则不能; C# 类型系统不够丰富,无法表达该约束。

null可以隐式转换为任何引用类型,因此编译器不会使用您的显式转换运算符。 尝试

string s = null;
o = (MyVO)s;

或者只是内联它

o = (MyVO)((string)s);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM