我收集了一些极端案例和脑筋急转弯,总是想听到更多。这个页面只涵盖了c#语言的一些细节,但我也发现了。net核心的东西也很有趣。例如,这里有一个没有在页面上,但我觉得不可思议:
string x = new string(new char[0]);
string y = new string(new char[0]);
Console.WriteLine(object.ReferenceEquals(x, y));
我希望输出False -毕竟,“new”(具有引用类型)总是创建一个新对象,不是吗?c#和CLI的规范都表明应该这样做。嗯,在这个特殊情况下不是这样。它输出True,并且在我测试过的框架的每个版本上都是这样。(不可否认,我还没有在Mono上尝试过……)
只是为了澄清,这只是我正在寻找的事情的一个例子-我并不是特别寻找对这个奇怪现象的讨论/解释。(这和普通的弦乐实习不一样;特别地,当调用构造函数时,字符串实习通常不会发生。)我真的是在要求类似的奇怪行为。
还有其他的宝藏吗?
想想这个奇怪的例子:
public interface MyInterface {
void Method();
}
public class Base {
public void Method() { }
}
public class Derived : Base, MyInterface { }
如果在同一个程序集中声明Base和Derived,编译器将使Base::方法为虚拟且密封(在CIL中),即使Base没有实现接口。
如果Base和Derived在不同的程序集中,编译Derived程序集时,编译器不会更改其他程序集,因此它将在Derived中引入一个成员,该成员将是MyInterface::Method的显式实现,它只会将调用委托给Base::Method。
编译器必须这样做,以支持与接口有关的多态分派,即它必须使该方法为虚拟。
c#支持数组和列表之间的转换,只要数组不是多维的,并且类型之间有继承关系,并且类型是引用类型
object[] oArray = new string[] { "one", "two", "three" };
string[] sArray = (string[])oArray;
// Also works for IList (and IEnumerable, ICollection)
IList<string> sList = (IList<string>)oArray;
IList<object> oList = new string[] { "one", "two", "three" };
注意,这是无效的:
object[] oArray2 = new int[] { 1, 2, 3 }; // Error: Cannot implicitly convert type 'int[]' to 'object[]'
int[] iArray = (int[])oArray2; // Error: Cannot convert type 'object[]' to 'int[]'