4

In Unity projects featuring explosions you often do this

private Dictionary<string, System.Action> explosions;

void .. initialize in your class constructor .. ()
    {
    explosions = new Dictionary<string, System.Action>();
    explosions.Add("huge", SomeCall);
    explosions.Add("huger", SomeCall);
    etc
    }

No problem, but it would make me happy if you could do this...

private Dictionary<string, System.Action> explosions =
    new Dictionary<string, System.Action>()
    {
    {"huge", SomeCall},
    {"huge", SomeCall},
    etc
    };

That would make me much happier ... you know that feeling when you sleep better, enjoy meals with more of a smile?

Of course, that doesn't work because:

Assets/scripts/objects/flite groups/ReallyTremendousExplosions.cs(134,26): error CS0236: A field initializer cannot reference the nonstatic field, method, or property `ReallyTremendousExplosions.SomeCall()'

Can anyone bring me peace on this?

Is there a way to get around the fact that you have to do it at initialization time?

Fattie
  • 27,874
  • 70
  • 431
  • 719

2 Answers2

3

I love dictionary initializers and I use them all the time. I feel your tears.

The answer is in your question, use a delegate!

public class ReallyTremendousExplosions
    {
        private delegate void ExplosionFactory(ReallyTremendousExplosions source);

        private Dictionary<string, ExplosionFactory> Explosions = new Dictionary<string, ExplosionFactory>()
        {
            { "huge", x => x.SomeMethod() },
            { "huger", x => x.SomeMethod() }
        };

        private void SomeMethod()
        {
              //Render massive explosions...
        }

        public void RenderNamedExplosion(string explosionName) {
            ExplosionsFactory explosionFactory;
            if (!Explosions.TryGet(explosionName, out explosionFactory) {
                    throw new NoSuchExplosionException(explosionName);
            }

            explosionFactory(this);
        }
    }

Code fully tested in Unity5/Mono.

Tewr
  • 3,713
  • 1
  • 29
  • 43
1

It seems that SomeCall is a non static method and that's why you can't use it in the field initializer. However you can put the initialization into constructor:

  public class MyClass {
    ...
    // non static method
    private void SomeCall() { ... }

    private Dictionary<string, System.Action> explosions;

    public MyClass() {
      explosions = new Dictionary<string, System.Action>() {
        {"huge", SomeCall},
        {"huger", SomeCall},
      };
    }
    ...
  }
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • Hi Dimitry - yes, **that's exactly what I did**. (In the code example `prep` (preparation) is obviously a initializer.) I want to know if there's a way to **get around that and do a field initialization!** Perhaps using a .. delegate, or something? It makes me very said I have to initialize in the constructor :/ – Fattie Feb 11 '16 at 15:16
  • @Joe Blow: No there's no such a way; in *.Net* (unlike *Java*) you can't reference non-static fields/methods/properties... in a field initializer. – Dmitry Bychenko Feb 11 '16 at 15:19