本文档列出了已知的 Roslyn 和 C# 标准之间的不一致之处,并按照标准的章节进行组织。
转换
从零值开始的隐式枚举转换
从 §10.2.4:
隐式枚举转换允许将任何整数类型并且值为零的常量表达式(§11.21)转换为任何enum_type,以及转换为底层类型为enum_type的任何nullable_value_type。
Roslyn 还对具有类型 float、double 和 decimal 的常量表达式进行隐式枚举转换:
enum SampleEnum
{
Zero = 0,
One = 1
}
class EnumConversionTest
{
const float ConstFloat = 0f;
const double ConstDouble = 0d;
const decimal ConstDecimal = 0m;
static void PermittedConversions()
{
SampleEnum floatToEnum = ConstFloat;
SampleEnum doubleToEnum = ConstDouble;
SampleEnum decimalToEnum = ConstDecimal;
}
}
不允许(正确)从具有类型 bool、其他枚举或引用类型的常量表达式进行转换。
成员查找
从 §12.5.1:
- 最后,移除隐藏成员后,查找结果被确定。
- 如果集由不是方法的单个成员组成,则此成员是查找的结果。
- 否则,如果集仅包含方法,则此组方法是查找的结果。
- 否则,查找会变得模棱两可,并且会发生绑定时间错误。
Roslyn 实现了一种对方法而非非方法符号的偏好:
var x = I.M; // binds to I1.M (method)
x();
System.Action y = I.M; // binds to I1.M (method)
interface I1 { static void M() { } }
interface I2 { static int M => 0; }
interface I3 { static int M = 0; }
interface I : I1, I2, I3 { }
I i = null;
var x = i.M; // binds to I1.M (method)
x();
System.Action y = i.M; // binds to I1.M (method)
interface I1 { void M() { } }
interface I2 { int M => 0; }
interface I : I1, I2 { }
有关已知类型/成员的假设
编译器可以自由地假设已知类型/成员的形状和行为。
它可能不会检查意外的约束、 Obsolete 属性或 UnmanagedCallersOnly 属性。
它可能会根据类型/成员的行为良好的预期执行一些优化。
注意:编译器应具有在缺少已知类型/成员时的恢复能力。
接口局部方法
接口分部方法是隐式非虚拟方法,与非分部接口方法和其他接口分部成员类型不同,请参阅 相关的中断性变更 和 LDM 2025-04-07。