为什么在将可空类型转换为Roslyn中的基类时没有转换?

时间:2014-12-01 14:35:02

标签: c# roslyn

让我们采取以下代码:

int? a = null;
int b = (int)a;

CastExpressionSyntax表达式提取(int)a

没有转换:

semanticModel.GetConversion(node) == {Identity}

没有符号(我希望Nullable<T> implicit operator T

semanticModel.GetSymbolInfo(node).Method == null

类型信息的两个值都相同

semanticModel.GetTypeInfo(node) == {Type = Int32, ConvertedType = Int32}
semanticModel.GetTypeInfo(node.Expression) == {Type = Int32?, ConvertedType = Int32?}

是否有正确的方法可以检测到可以为空的nullable为nullable,或者我需要手动查看其中一个类型infos是否为空,而其他类型信息是否可以为空?

不同行为的示例:

让我们采取结构:

 public struct N<T> where T : struct
 {
     public static explicit operator T(N<T> value)
     {
        return default(T);
     }
 }

之前使用它就像可以为空
 N<int> e;
 int d = (int) e;

@Kirk Woll是正确的,GetConversionGetTypeInfo是相同的,但GetSymbolInfo会返回public static explicit operator T(N<T> value)方法。

Nullable具有完全相同的方法,但不会返回。

没有调用操作符emmited compiller会生成对Value属性的直接调用。

IL_0001:  ldloca.s    00 // a
IL_0003:  initobj     System.Nullable<System.Int32>
IL_0009:  ldloca.s    00 // a
IL_000B:  call        System.Nullable<System.Int32>.get_Value
IL_0010:  stloc.1     // b

1 个答案:

答案 0 :(得分:3)

在施法操作中:

int b = (int)a;

你有演员表达:

(int)a

CastExpressionSyntax具有Expression属性(代表a)和Type属性(代表int)。因此,在我使用VisitCastExpression执行此操作时,我查询两个值以确定转换的from和to:

var typeInfo = model.GetTypeInfo(node.Expression);
var originalType = typeInfo.Type;
var convertedType = typeInfo.ConvertedType;
var destinationType = model.GetTypeInfo(node.Type).Type;

destinationType始终是您投射的内容(在您的情况下为int)。 originalType是表达式经过任何隐式转换之前的类型。 convertedType是表达式经过任何隐式转换后的类型。在您的示例中,convertedTypeoriginalType都应为int?

因此,我并不完全确定你希望Roslyn以何种方式表现出不同的行为,但在我看来,我的行为与我期望的完全一样。

至于为什么没有返回符号信息,我的猜测是编译器实际上没有发出调用该运算符重载的代码并隐式处理这样的转换。因此,如果提供该符号,那将是不正确的。