Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何从Nullable强制转换<;T>;明确地_C#_Casting_Nullable_Implicit Conversion - Fatal编程技术网

C# 如何从Nullable强制转换<;T>;明确地

C# 如何从Nullable强制转换<;T>;明确地,c#,casting,nullable,implicit-conversion,C#,Casting,Nullable,Implicit Conversion,我已经使用从long到MyCustomValueType的隐式强制转换运算符定义了自定义值类型MyCustomValueType public struct MyCustomValueType { private readonly long number; public MyCustomValueType(long? number) { this.number = number.GetValueOrDefault(0); } publi

我已经使用从long到MyCustomValueType的隐式强制转换运算符定义了自定义值类型MyCustomValueType

public struct MyCustomValueType
{
    private readonly long number;

    public MyCustomValueType(long? number)
    {
        this.number = number.GetValueOrDefault(0);
    }

    public static implicit operator MyCustomValueType(long number)
    {
        return new MyCustomValueType(number);
    }
}
然后,编译器允许我执行以下操作:

// ...
long? value = null;
MyCustomValueType myCustomValueType = (MyCustomValueType)value;
Console.WriteLine(myCustomValueType);
在后台,编译器通过强制转换将语句转换为:

MyCustomValueType myCustomValueType = ((long?)null).Value;
我想知道这是怎么发生的(或者更好地说是为什么发生的)?为什么编译器甚至允许显式强制转换没有定义任何人。编译器在这里应用什么规则


我可能还应该提到,当MyCustomValueType仅定义用于转换的显式运算符时,也可以进行这种转换,例如:

public static explicit operator MyCustomValueType(long number)
但在这种情况下,我不知何故接受了编译器的工作并理解了它。隐式运算符的情况确实令人困惑。有人能解释一下吗

为什么编译器甚至允许显式强制转换没有定义任何人。编译器在这里应用什么规则

它适用于C规范第6.4.2节中定义的提升转换:

给定一个已使用的定义转换运算符,该运算符将不可为空的值类型
S
转换为不可为空的值类型
T
,则存在一个提升的转换运算符,该运算符将从
S
转换为
T
。此提升的转换运算符执行从
S
S
的展开,然后执行从
S
T
的用户定义转换,然后执行从
T
T
的包装,除非空值
S
直接转换为空值
T

所以你可以认为它实际上是:

long? value = null;
long tmp1 = (long) value;       // Unwrapping
MyCustomValueType tmp2 = tmp1;  // User-defined conversion
MyCustomValueType? tmp3 = tmp2; // Wrapping
MyCustomValueType myCustomValueType = (MyCustomValueType) tmp3; // Unwrapping

老实说,我认为这并不特别令人惊讶——特别是,如果您理解当声明的转换运算符是显式的时某些东西是可行的,那么当声明的转换运算符是隐式的时,同样的用法也是可行的,这是值得期待的。(当然,不一定是相反的。)

感谢您的解释,我不知何故没有意识到这个显式强制转换代码的目的是将Nullable转换为T。