让我们看下面的代码:
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?}
是否有正确的方法来检测可空到不可空的强制转换,或者我需要手动查看类型信息中的一个是否可以为空而另一个不是?
不同行为的示例:
让我们来看看结构:
public struct N<T> where T : struct
{
public static explicit operator T(N<T> value)
{
return default(T);
}
}
并且像之前的nullable一样使用它
N<int> e;
int d = (int) e;
@Kirk Woll 是对的 GetConversion
和 GetTypeInfo
会是一样的,但是 GetSymbolInfo
会返回 public static explicit operator T(N<T> value)
方法。
Nullable 具有完全相同的方法,但不返回。
没有调用运算符 emmited 编译器生成对 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
最佳答案
在强制转换操作中:
int b = (int)a;
你有转换表达式:
(int)a
CastExpressionSyntax
有一个Expression
属性(代表a
)和Type
属性(代表整数
)。因此,在我使用 VisitCastExpression
实现此方法时,我查询两个值以确定转换的起始和终止:
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
是表达式经过任何隐式转换后的类型。在您的示例中,convertedType
和 originalType
都应为 int?
。
所以我不完全确定您希望 Roslyn 以何种方式表现不同,但在我看来,它的表现完全符合我的预期。
至于为什么没有返回符号信息,我的猜测是编译器实际上不会发出调用该运算符重载的代码并隐式处理此类转换。因此,如果它提供了该符号,那将是不正确的。
关于c# - 为什么在将可空类型转换为 Roslyn 中的基类时没有转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27230659/