首页 > 解决方案 > CS1503 无法转换 MyType?到我的类型

问题描述

我似乎无法理解可空性在 C# 8 中的工作原理。在下面的 IF 表达式中,很明显它myType不为。我仍然收到一个编译器错误,说它可能MyType OR null不是MyType.

public Method(MyType mytpe)
{
    System.Console.WriteLine("Meh");
}

public class AwesomeType
{
    public MyType? MyType { get; set; }
}

//...
var awesome = new AwesomeType();
var myType = awesome.MyType;
if (myType != null)
{
    Method(myType); // CS1503 Cannot convert MyType? to MyType
}

以下工作正常

var awesome = new AwesomeType();
var myType = awesome.MyType;
if (myType != null)
{
    Method(myType.Value);
}

我认为第一种方法应该可行,因为编译器可以在 if 条件的真实块中推断不可为空性。为什么编译器仍然抱怨?

标签: c#nullable

解决方案


为什么编译器仍然抱怨?

这与可空对象在 C# 中的工作方式有关。?表示对象可以为空的运算符基本上告诉编译器“嘿编译器 - 这个对象可能为空,没关系。”

这对您有什么作用,例如,bool?允许您表示通常不打算使用的状态。

通常 abool只能是true并且false如果它从未被初始化它可能null. 如果bool从未初始化访问它的值将抛出一个NullReferenceException.

同时bool?(表示可空布尔)对编译器说“如果布尔为空,则将其null视为它的值,而不是抛出异常并抱怨它没有值。”(在简化意义上)

使用可空类型的诀窍在于,它们不会像不可空类型那样被隐式处理。它们基本上是完全不同的对象,除非你这么说。

当您考虑它时,这很有意义。如果您可以设置一个普通的布尔值,例如bool isLightOn = true;并将其设置为isLightOn = null;,那将是非常奇怪的,这甚至意味着什么?灯会关掉吗,不,那是假的……,它会闪烁灯吗?null当您将变量设置为该变量通常不使用的值(如)时,编译器不知道您打算发生什么。这是好事!它会导致各种奇怪的问题。

这会导致您遇到的问题。

bool? isLightOn = false;

// compiler checks to see if a bool? can have a null state
// it determines that bool? can be true, false, or null
// it says this line is okay
if(isLightOn != null)
{
    // compiler says the variable isn't null, 
    // but it still CAN be null, for example, if something within this code block changes it's value,
    //  or if that variable is accessed by another thread
    // becuase of this the compiler will not consider this light 
    // as either true, false(a normal bool) it says 'there's still
    // a possibility that by the time it's used it may not be 
    // either true, or false, therefor it should be considered as
    //  being maybe null in my eyes(the compiler).'

    // compiler checks to see if the object you're passing as a parameter is a valid object
    // compiler sees that your object can be true, false, or null
    // compiler says 'if i give this method this object without asking the programmer if it's okay, it may break the program becuase the method doesn't know how to deal with null values' 
    TestLight(isLightOn);

    // compiler checks to see if the object you're passing as a parameter is a valid object
    // compiler sees that the programmer explicitly told it to ignore the null value and treat is as if it were false, and allows you to pass that variable as parameter
    TestLight((bool)isLightOn);
}
void TestLight(bool lightOn)
{
}

当您检查可空对象是否为空时,只需检查它的值。由于这是对象处于的有效状态,因此编译器会继续工作并且不会抱怨。

null当您尝试将该值实际用于使用不可空对象作为参数的东西时,我们会遇到这样的问题,如果对象状态不是有效状态,编译器应该如何知道您想要做什么?那个物体?

因此,它将对象的可空和不可空版本视为完全不同的类型,但两者之间有显式转换。

其原因可以归结为您试图以一种会丢失信息或有损操作的方式使用变量,如果您愿意的话。

编译器不会假设您要忽略可空对象的有效值。

它迫使您说'嘿编译器,将此可为空的对象视为不可为空的对象,如果它的值不是预期的,请将其更改为预期值(默认值)。因为bool?如果有效值是null并且您说“将其视为不可为空的布尔值”(通过使用显式转换(bool)bool?,编译器会说“好的!null基本上是default这样,当您将其作为参数传递时,它就是新值”。


推荐阅读