Jonathan Wood
Jonathan Wood

Reputation: 67195

Storing Reference to Non-Static Method

I'm trying to create a collection of values that each correspond to an action. This way, I'll be able to search the collection for a particular value and then call the associated action in a generic way.

So, here was my first stab at it:

public class CommandInfo
{
    public string Name { get; set; }
    public Action<RunArgument> Action { get; set; }
}

public class MyClass
{
    public List<CommandInfo> Commands = new List<CommandInfo>
    {
        new CommandInfo { Name = "abc", Action = AbcAction } // <== ERROR HERE
    };

    public void AbcAction(RunArgument arg)
    {
        ; // Do something useful here
    }
}

In this case, the declaration of the new CommandInfo inside the Commands collection gives me the error:

A field initializer cannot reference the non-static field, method, or property 'MyNameSpace.MyClass.AbcAction(MyNameSpace.RunArgument)'

Surely there must be a way to store a reference to a non-static method like this. Can someone help me out?

Upvotes: 3

Views: 229

Answers (2)

shf301
shf301

Reputation: 31394

The problem isn't that you can't store a reference to a non-static member, it is that you cannot reference a non-static member in a field initializer. Field initializers can only reference static or constant values. Move the initialization of Commands to the constructor and it will work.

public class CommandInfo
{
    public string Name { get; set; }
    public Action<RunArgument> Action { get; set; }
}

public class MyClass
{
    public List<CommandInfo> Commands;

    public MyClass 
    {
        Commands = new List<CommandInfo>
        {
            new CommandInfo { Name = "abc", Action = AbcAction }
        };
    }

    public void AbcAction(RunArgument arg)
    {
        ; // Do something useful here
    }
}

Upvotes: 5

Jon Skeet
Jon Skeet

Reputation: 1500495

Surely there must be a way to store a reference to a non-static method like this. Can someone help me out?

There is, just not within a field initializer. So this works fine:

public List<CommandInfo> Commands = new List<CommandInfo>();

public MyClass()
{
    Commands.Add(new CommandInfo { Name = "abc",
                                   Action = AbcAction });
}

... or perform the whole assignment within the constructor. Note that this doesn't really have anything to do with delegates - it's incidental, on the basis that you're effectively referring to this.AbcAction. In every other way, it's equivalent to this problem:

public class Foo
{
    int x = 10;
    int y = this.x; // This has the same problem...
}

(I hope you don't really have a public field, of course...)

Upvotes: 6

Related Questions