通过C#中的Action传递结构不会编译

时间:2011-08-03 12:58:16

标签: c# delegates

我有一个可以正常工作和编译的代码,我将Action定义为:

Action<double, double, double ....> OnBlah;

现在我有超过16个参数,所以我想传递一个结构,所以我将动作定义为:

Action<structName> OnBlah;

但我在C#编译器中遇到一个错误,指出structName未初始化。这很奇怪,因为:

一个。以前在代码中我直接从结构中传递了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) => { };
        }
    }
}

2 个答案:

答案 0 :(得分:1)

这不是编译器错误。您需要首先初始化结构,就像编译器所说的那样。大概你的错误实际上是在调用委托的代码中,因为没有别的意义。

当您使用16参数double版本调用委托时,会初始化double参数。如果您尚未初始化它们,那么编译器将发出相同的错误。例如:

private static void actDouble(double d)
{
}

static void Main(string[] args)
{
    double d;
    Action<double> act = actDouble;
    act(d);//error on this line
}

无法使用以下错误进行编译:

error CS0165: Use of unassigned local variable 'd'

在这方面结构没有什么特别之处。

作为一般规则,当您遇到语法错误时,您的第一个猜测绝不应该是这是编译器错误。编译器错误非常罕见,尤其是在广泛使用的编译器中。


修改添加实际代码的问题后更新

Test test;
int b = 0;
if (b == 4)
{
    test.a = 5;
}
OnBlah(test);

编译器不确定test是否已完全初始化。它不进行程序流分析。您可以通过确保编译器知道结构已完全初始化来解决问题。

答案 1 :(得分:0)

Action<structName> OnBlah;

永远不会引起你引用的错误;如果无法解析ActionstructName这两种类型中的任何一种,它会抱怨 - 如果泛型类型参数不合适,它会抱怨,但这是预期的。

如果OnBlah字段,它会自动初始化为null;如果是变量,则需要在使用前进行分配。它可以分配给null,但如果是这样,当您尝试调用它时它将在运行时失败(除非您进行空检查)。那么我们来调用;如果我们假设非null,则需要提供一个参数,即

OnBlah(someValue); // or OnBlah.Invoke(someValue);

此处,如果someValue 尚未定义则会出错;如果不是明确分配它将会出错。对于明确的分配,分配字段;除非已初始化,否则不会有变量。

对于结构体,通过使用构造函数(或其他返回值的方法),,通过手动设置 <来初始化值 em>每个 字段(这是不可能的,因为a:结构应该是不可变的,而b:字段应该是私有的。)