可能是VisualStudio2015中的C#编译器错误我认为是编译错误。以下控制台应用程序在使用VS2015编译时可以完美编译和执行:}publicstructMyStruct{publicstaticreadonlyMyStructEmpty=newMyStruct();但现在它变得很奇怪:这段代码编译,但在执行时抛出TypeLoadException。namespaceConsoleApplication1{classProgram{staticvoidMain(string[]args){varx=MyStruct.空的;}publicstructMyStruct{publicstaticreadonlyMyStruct?空=空;}}}你有遇到同样的问题吗?如果是这样,我将向Microsoft提出问题。代码看起来毫无意义,但我使用它是为了提高可读性和消除歧义。我有不同的重载方法,例如voidDoSomething(MyStruct?arg1,stringarg2)voidDoSomething(stringarg1,stringarg2)以这种方式调用方法...myInstance.DoSomething(null,"Helloworld!")...不会编译。调用myInstance.DoSomething(default(MyStruct?),"Helloworld!")或myInstance.DoSomething((MyStruct?)null,"Helloworld!")有效,但看起来很难看。我更喜欢这个:myInstance.DoSomething(MyStruct.Empty,"Helloworld!")如果我将Empty变量放在另一个类中,一切正常:publicstaticclassMyUtility{publicstaticreadonlyMyStruct?空=空;奇怪的行为,不是吗?更新2016-03-29我在这里开了一张票:http://github.com/dotnet/roslyn/issues/10126更新2016-04-06在这里开了一张新票:https://github.com/dotnet/coreclr/issues/4049这不是2015年的错误,但可能是C#语言错误。下面的讨论涉及为什么实例成员不能引入循环,以及为什么Nullable会导致此错误,但不应应用于静态成员。我将其归档为语言错误,而不是编译器错误。在VS2013中编译此代码会产生以下编译错误:类型为“System.Nullable”的结构成员“ConsoleApplication1.Program.MyStruct.Empty”导致结构布局中出现循环快速搜索找到了这个答案:Owningapropertythatcontains本身作为成员结构是无效的。不幸的是,用于值类型的可为空实例的System.Nullable类型也是一种值类型,因此必须具有固定大小。是不是很容易想到MyStruct?作为参考类型,但实际上不是。MyStruct的大小?我的结构?基于MyStruct的大小...这显然在编译器中引入了一个循环。例如:publicstructStruct1{publicinta;公共诠释b;公共诠释c;}公共结构结构2{公共结构1?;}使用System.Runtime.InteropServices.Marshal.SizeOf()你会发现Struct2是16字节,说明Struct1?不是引用,而是比Struct1(标准填充大小)长4个字节的Struct1。这里没有发生什么为了回应JuliusDepulla的回答和评论,这是访问静态Nullable字段时实际发生的情况。从这段代码:publicstructfoo{publicstaticint?空=空;}publicvoidMain(){Console.WriteLine(foo.Empty==null);这是从LINQPad生成的IL:IL_0000:ldsfldaUserQuery+foo.EmptyIL_0005:调用System.Nullable.get_HasValueIL_000A:ldc.i4.0IL_000B:ceqIL_000D:调用System.Console.WriteLineIL_0012:ret第一条指令获取静态字段foo.Empty的地址并将其压入上级堆栈。由于Nullable是结构而非引用类型,因此地址保证为非空。接下来,调用Nullable隐藏成员函数get_HasValue来检索HasValue属性值。这不会导致空引用,因为如前所述,无论地址中包含什么值,值类型字段的地址都必须是非空的。剩下的只是将结果与0进行比较并将结果发送到控制台。在此过程中,无论如何您都可以“在类型上调用null”。值类型没有空地址,因此对值类型的方法调用不能直接导致空对象引用错误。这就是我们不称它们为引用类型的原因。首先,分析这些问题以制造尽可能小的复制器很重要,这样我们就可以缩小问题所在的范围。原始代码中存在三个转移注意力的问题:readonly、static和Nullable。没有必要重复这个问题。这是一个最小的复制:structN{}structM{publicNE;}classP{staticvoidMain(){varx=default(M);}}这会在当前版本的VS中编译,但是运行时会抛出类型加载异常。现在让我们做一些实验。如果我们制作N和M课程怎么办?我会告诉你结果:我们可以继续讨论这个问题是否只有当M在某种意义上“直接”引用自己时才会重现,或者“间接”循环是否也可以重现这个错误。(后者是正确的。)正如科里在他的回答中指出的那样,我们也可以问“类型必须是通用的吗?”不;有一个复制器比它更简洁,没有泛型。但我认为我们对复制子的讨论已经够多了,现在开始讨论手头的问题,即“它是一个错误吗?如果是,在什么地方?”显然这里出了什么问题,我今天没有时间来解决责任应该落在何处。这里有一些想法:那么现在让我们总结一下可能性:为了论证,让我们假设第二个是真的。关于C#,我们现在能说些什么?一些可能性:总而言之,我们的可能性是:这四种可能性之一必须为真。我不知道是哪一个。如果让我猜,我会选第一个;我看不出为什么CLR类型的加载程序应该对此不屑一顾。但也许有一个我不知道的充分理由;希望CLR类型加载语义方面的专家能参与进来。更新:此问题在此处跟踪:https://github.com/dotnet/roslyn/issues/10126总结C#团队在该问题中的结论:C#和CLR团队就是这样;跟进他们。如果您对此问题有任何疑虑,请发布跟踪问题而不是此处。现在我们已经介绍了是什么和为什么,下面是解决问题的方法,而无需等待各种.NET团队追踪问题并弄清楚如何处理它。问题似乎仅限于作为值类型的字段类型,并且它们以某种方式引用此类型,作为通用参数或静态成员。例如:publicstructA{publicstaticBb;}publicstructB{publicstaticAa;呃,我现在觉得很脏。糟糕的OOP,但它表明问题存在而无需以任何方式调用泛型。因此,因为它们是值类型,所以类型加载器确定存在由于static关键字而应该忽略的循环。C#编译器足够聪明,可以解决这个问题。它是否应该有一个规范,我没有评论。但是,通过将A或B更改为类,问题就消失了:publicstructA{publicstaticBb;}publicclassB{publicstaticAa;因此,可以通过使用引用类型存储实际值并将字段转换为属性来避免此问题:publicstructMyStruct{privatestaticclass_internal{publicstaticMyStruct?空=空;}公共静态MyStruct?空=>_internal.empty;慢了很多,因为它是一个属性而不是一个字段,调用它会调用get方法,所以我不会将它用于性能关键代码,但作为一种解决方法,它至少可以让你这样做,直到有一个适当的解决方案。如果事实证明这不是固定的,至少我们有一个可以用来解决它的问题。以上就是C#学习教程:可能就是VisualStudio2015中C#编译错误分享的全部内容,如果对你有用,需要进一步了解C#学习教程,希望大家多多关注.本文来自网络收集,不代表立场,如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
