简体   繁体   English

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

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

I have an explicit operator on the class MyVO , which should be non-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);
    }

However, (MyVO)null will not raise an exception.但是, (MyVO)null不会引发异常。 The body of the method will not be run.该方法的主体将不会运行。

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

How to make sure it's not null?如何确保它不为空?

How to make sure it's not null?如何确保它不为空?

By "it" I assume you mean "the result of the cast from null to MyVO ". “它”我假设您的意思是“从nullMyVO ”。 If that is not what you mean, please clarify the question.如果这不是您的意思,请澄清问题。

You cannot.你不能。

An important rule of C# is a user-defined conversion never "wins" when it conflicts with a built-in conversion . C# 的一个重要规则是用户定义的转换在与内置转换冲突时永远不会“获胜” It is legal to convert null to any class type, and so a cast of MyVO on the expression null will always result in a null reference.null转换为任何类类型都是合法的,因此MyVO对表达式nullMyVO始终导致 null 引用。 The compiler does not even consider the user-defined conversions if a built-in conversion works.如果内置转换有效,编译器甚至不会考虑用户定义的转换。 (Believe me; I wrote that code!) (相信我;我写了那个代码!)

As D Stanley's answer correctly points out, if the null is the value of any expression of type string then the user-defined conversion is called;正如 D Stanley 的回答正确指出的那样,如果nullstring类型的任何表达式的,则调用用户定义的转换; there is no built-in conversion from string to MyVO so the compiler looks for an applicable user-defined conversion and finds one.没有从stringMyVO内置转换,因此编译器会查找适用的用户定义转换并找到一个。

Since it hurts when you do what you're doing, you should probably stop doing what you are doing.因为当你做你正在做的事情时会很痛,你应该停止做你正在做的事情。 An explicit conversion is probably not the right way to implement the desired behaviour.显式转换可能不是实现所需行为的正确方法。

I guess my question should be how to make MyVO not nullable.我想我的问题应该是如何使MyVO不可为空。

Upgrade to C# 8. C# 8 supports non-nullable annotations on reference types.升级到 C# 8。C# 8 支持对引用类型进行不可为空的注释。

Note that the non-nullable annotation should be properly thought of as an annotation .请注意,不可为空的注释应该被正确地视为annotation The type system does not guarantee that the value of a variable annotated with a non-nullable annotation will never be observed to be null.类型系统不保证用不可为空的注释注释的变量的值永远不会被观察到为空。 Rather, it does its best to warn you when the code looks like it is wrong.相反,它会尽最大努力在代码看起来有误时向您发出警告。


While we are looking at your code, I notice that you are using ValueObject<T> , which I assume you have obtained from something like在我们查看您的代码时,我注意到您正在使用ValueObject<T> ,我假设您是从类似的东西中获得的

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

Let me take this opportunity to caution you that there are pitfalls to using this pattern;让我借此机会提醒您,使用这种模式存在缺陷; the constraint that you think or want to be applied to T is not the constraint that is applied to T .认为希望被应用于约束T不是适用于约束T We often see things like this:我们经常看到这样的事情:

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

If we have class Banana : V<Banana> then Banana.M takes as its argument a Banana , which is what we want.如果我们有class Banana : V<Banana>那么Banana.M将一个Banana作为它的参数,这就是我们想要的。 But now suppose we have class Giraffe : V<Banana> .但是现在假设我们有class Giraffe : V<Banana> In this scenario, Giraffe.M does not take a giraffe;在这种情况下, Giraffe.M不带长颈鹿; it takes a banana, even though Giraffe has no relationship with Banana at all.它需要一根香蕉,尽管GiraffeBanana根本没有关系。

The constraint does not mean that M always takes an instance of its own class.约束并不意味着M始终把自己的类的实例。 If you are trying to construct a generic type with this kind of constraint in C#, you cannot;如果您尝试在 C# 中使用这种约束构造泛型类型,则不能; the C# type system is not rich enough to express that constraint. C# 类型系统不够丰富,无法表达该约束。

null can be implicitly converted to any reference type, so the compiler is not using your explicit cast operator. null可以隐式转换为任何引用类型,因此编译器不会使用您的显式转换运算符。 try尝试

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

or just inline it或者只是内联它

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

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

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