简体   繁体   中英

Passing a struct via an Action in C# does not compile

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) => { };
        }
    }
}

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:

private static void actDouble(double d)
{
}

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

This fails to compile with the following error:

error CS0165: Use of unassigned local variable 'd'

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

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

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;

can never raise the error you cite; if either of the two types Action or structName 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 to null , 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, ie

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

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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM