在 C# 中通过 Action 传递结构无法编译
我有一个可以完美运行和编译的代码,其中我有一个 Action 定义为:
Action<double, double, double ....> OnBlah;
现在我有超过 16 个参数,所以我想传递一个结构体,所以我将操作定义为:
Action<structName> OnBlah;
但我在 C# 中遇到错误编译器提示 structName 未初始化。这很奇怪,因为:
A. 以前在代码中我直接从结构中传递了 OnBlah 的双参数。
B. 结构体通过定义进行初始化。
我正在使用 VS 2010,我猜这是一个编译器错误?
添加了编译器错误的重现代码:
namespace CompilerBug
{
struct Test
{
public double a;
}
class Program
{
static Action<Test> OnBlah;
static void DoesCompileOk()
{
Test test;
test.a = 5;
OnBlah(test);
}
static void DoesNotCompileOk()
{
Test test;
int b = 0;
if (b == 4)
{
test.a = 5;
}
OnBlah(test);
}
static void Main(string[] args)
{
OnBlah = (t) => { };
}
}
}
I have a code which works and compiles perfectly, where I have an Action defined as:
Action<double, double, double ....> OnBlah;
Now I have more than 16 params, so I want to pass a struct instead, so I defined the action as:
Action<structName> OnBlah;
But I get an error in the C# compiler that says that structName is not initialized. This is weird since:
A. Previously in the code I passed the double parameters for OnBlah from the struct directly.
B. Structs are initialized by definition.
I'm using VS 2010, I'm guessing this is a compiler bug ?
Added reproduction code for the compiler bug:
namespace CompilerBug
{
struct Test
{
public double a;
}
class Program
{
static Action<Test> OnBlah;
static void DoesCompileOk()
{
Test test;
test.a = 5;
OnBlah(test);
}
static void DoesNotCompileOk()
{
Test test;
int b = 0;
if (b == 4)
{
test.a = 5;
}
OnBlah(test);
}
static void Main(string[] args)
{
OnBlah = (t) => { };
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这不是编译器错误。您需要首先初始化结构,就像编译器所说的那样。据推测,您的错误实际上是在调用委托的代码中,因为没有其他任何意义。
当您使用 16 个参数双精度版本调用委托时,双精度参数已初始化。如果您没有初始化它们,那么编译器将发出相同的错误。例如:
编译失败,并出现以下错误:
在这方面,结构没有什么特别之处。
作为一般规则,当您遇到语法错误时,您的第一反应绝不应该是这是编译器错误。编译器错误非常罕见,尤其是在像本编译器这样广泛使用的编译器中。
在编辑添加真实代码的问题后进行更新
编译器不确定
test
是否已完全初始化。它不进行程序流程分析。您可以通过确保编译器知道该结构已完全初始化来解决该问题。This is not a compiler bug. You need to initialize the struct first, like the compiler says. Presumably your error is actually in the code which invokes the delegate since nothing else makes sense.
When you were invoking the delegate with your 16 parameter double version, the double parameters were initialized. If you had not initialized them, then the compiler would have emitted the same error. For example:
This fails to compile with the following error:
There is nothing special about structs in this regard.
As a general rule, your first guess when you encounter a syntax error should never be that this is a compiler bug. Compiler bugs are exceedingly rare, especially in a compiler as widely used as this one.
Update following the edit to the question which added real code
The compiler is not sure that
test
is fully initialized. It does not do program flow analysis. You can fix the problem by making sure that the compiler knows that the struct is fully initialized.永远不能提出您引用的错误;如果
Action
或structName
两种类型中的任何一个无法解析,它会抱怨 - 如果泛型类型参数不合适,它会抱怨,但是这是预期的。如果
OnBlah
是一个字段,它会自动初始化为 null;如果它是一个变量,则需要在使用前对其进行赋值。它可以被分配给null
,但如果是这样,当您尝试调用它时,它将在运行时失败(除非您进行空检查)。那么我们来调用;如果我们假设非空,则需要提供一个参数,即这里,如果
someValue
尚未定义,则会出错;如果没有明确分配,就会出错。对于明确赋值,字段被赋值;除非初始化,否则变量不会。对于结构体,可以通过使用构造函数(或返回值的其他方法)来初始化值,或者通过手动设置每个 字段(这应该是不可能的,因为 a: 结构应该是不可变的,而 b: 字段应该是私有的)。
can never raise the error you cite; if either of the two types
Action
orstructName
can't be resolved, it'll complain - and if the generic type argument isn't suitable it'll complain, but that is expected.If
OnBlah
is a field it is automatically initialized to null; if it is a variable it will need to be assigned before use. It could be assigned tonull
, but if so it will fail at runtime when you try to invoke it (unless you do a null-check). So then we come to invoke; if we assume non-null, you need to supply an argument, i.e.here, if
someValue
has not been defined it will error; it if is not definitely assigned it will error. For definite assignment, fields are assigned; variables are not unless initialized.In the case of structs, a value is initialized either by using the constructor (or another method that returns the value), or by manually setting every field (which shouldn't be possible, since a: structs should be immutable, and b: fields should be private).