请考虑以下代码.看起来完全有效的C#代码对吗?
//Project B
using System;
public delegate void ActionSurrogate(Action addEvent);
//public delegate void ActionSurrogate2();
// Using ActionSurrogate2 instead of System.Action results in the same error
// Using a dummy parameter (Action<double, int>) results in the same error
// Project A
public static class Class1 {
public static void ThisWontCompile() {
ActionSurrogate b = (a) =>
{
a(); // Error given here
};
}
}
Run Code Online (Sandbox Code Playgroud)
我得到一个编译错误'委托'动作'不接受0参数.使用(Microsoft)C#4.0编译器在指定位置.请注意,您必须在另一个项目中声明ActionSurrogate才能显示此错误.
它变得更有趣:
// Project A, File 1
public static class Class1 {
public static void ThisWontCompile() …Run Code Online (Sandbox Code Playgroud) 以下C#代码无法编译:
public class A
{
public interface B { }
}
public class C
: A,
C.B // Error given here: The type name 'B' does not exist in the type 'C'.
{ }
public class D : C.B // Compiles without problems if we comment out 'C.B' above.
{ }
Run Code Online (Sandbox Code Playgroud)
根据C#4.0规范(第10.1.4.1段),此行为是正确的:
在确定B类的直接基类规范A的含义时,暂时假定B的直接基类是对象.直观地,这确保了基类规范的含义不能递归地依赖于它自己.
我的问题是:为什么不允许这种行为?
Intellisense对它没有任何问题 - 虽然我知道这并没有说太多,但在见证Visual Studio崩溃后Intellisense试图理解一些与变种泛型的邪恶类组合.
在互联网上搜索规范中的上述引用并没有产生任何结果,所以我猜这还没有在任何地方提出.
我为什么在意?我设计了以下代码:
// The next three classes should really be interfaces,
// but I'm going to override a method later on to …Run Code Online (Sandbox Code Playgroud) 下面的代码无法在gcc 7.3.0和clang 6.0.0上编译(但似乎在MSVC下编译正常):
#include <utility>
struct IncompleteType;
template<typename T>
struct Container {
T value;
};
using Uninstantiatable = Container<IncompleteType>;
auto foo() -> decltype(static_cast<Uninstantiatable const&>(std::declval<Uninstantiatable const&>())) {
throw 1;
}
Run Code Online (Sandbox Code Playgroud)
我得到的错误是这样的:
<source>:7:7: error: field has incomplete type 'IncompleteType'
T value;
^
<source>:12:24: note: in instantiation of template class 'Container<IncompleteType>' requested here
auto foo() -> decltype(static_cast<Uninstantiatable const&>(std::declval<Uninstantiatable const&>())) {
^
<source>:3:8: note: forward declaration of 'IncompleteType'
struct IncompleteType;
^
1 error generated.
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud)
亲自尝试一下:https://godbolt.org/g/5AW37K
但是,如果我替换第10行,它就会编译
using Uninstantiatable …Run Code Online (Sandbox Code Playgroud) 我正在构建一个使用相对较大的表来完成其工作的应用程序(确切地说是LR表).因为我正在生成代码并且表格不是那么大,所以我决定通过生成使用C#集合初始化程序语法在我生成的程序启动时初始化表的代码来序列化我的表:
public static readonly int[,] gotoTable = new int[,]
{
{
0,1,0,0,0,0,0,0,0,0,0,0,0,0,(...)
},
{
0,0,4,0,5,6,0,0,0,0,0,7,0,0,(...)
},
(...)
Run Code Online (Sandbox Code Playgroud)
奇怪的是,当我生成一个只有几十万个条目的表时,我生成的应用程序在启动时因StackOverflowException而崩溃.C#编译器编译得很好; 表生成应用程序也运行得很好.实际上,当我切换到Release模式时,应用程序确实启动了.OutOfMemoryException可能已经有了一些意义,但即便如此,我使用的表对于OutOfMemoryException来说是小的.
重现此代码的代码:
警告:在发布模式下尝试下面的代码让我崩溃了Visual Studio 2010; 注意失去未得救的工作.此外,如果生成编译器生成大量错误的代码,Visual Studio也将挂起.
//Generation Project, main.cs:
using (StreamWriter writer = new StreamWriter("../../../VictimProject/Tables.cs"))
{
writer.WriteLine("using System;");
writer.WriteLine("public static class Tables");
writer.WriteLine("{");
writer.WriteLine(" public static readonly Tuple<int>[] bigArray = new Tuple<int>[]");
writer.WriteLine(" {");
for (int i = 0; i < 300000; i++)
writer.WriteLine(" new Tuple<int>(" + i + "),");
writer.WriteLine(" };");
writer.WriteLine("}");
}
//Victim Project, …Run Code Online (Sandbox Code Playgroud) 何时通过单播代表进行多播委托是否有用?
我使用代理很多,主要是与C#lambdas结合使用,但我从未感觉到使用C#委托的多播方面的冲动,即我从来没有想过在一个委托中将多个委托组合在一起.因此,我很好奇多播代表在什么样的情况下是有用的 - 我只能想到你可以通过其他方式轻松实现功能的例子,比如链接代表或将它们放在列表中.
特别是,Eric Lippert 在这里给出的答案给人的印象是,即使C#团队有时会忘记代表的多播性.
c# ×4
.net ×2
c++ ×1
collections ×1
compiler-bug ×1
delegates ×1
generics ×1
inheritance ×1
lambda ×1
templates ×1