开发者

C# method from derived class as delegate in base constructor

Why is the following C# not legal? Does there exist a proper workaround?

public class Base
{
    public Base(Func<double> func) { }
}

public class Derived : Base
{
    public Derived() : base(() => Method()) <开发者_JAVA技巧;-- compiler: Cannot access non-static method 'Method' in static context
    {
    }

    public double Method() { return 1.0; }
}


It's effectively referring to "this" within the arguments to the base constructor, which you can't do.

If your delegate really doesn't need access to this (which your sample doesn't) you can just make it static. You could also use a method group conversion to make it simpler:

public class Base
{
    public Base(Func<double> func)
    {
        double result = func();
    }
}

public class Derived : Base
{
    public Derived() : base(Method)
    {
    }

    public static double Method() { return 1.0; }
}

If you do need to use "this", you could:

  • Make it a virtual method instead of calling a delegate
  • Make it a static method which takes an appropriate instance, e.g.

    public class Base
    {
        public Base(Func<Base, double> func)
        {
            double result = func(this);
        }
    }
    
    public class Derived : Base
    {
        public Derived() : base(x => Method(x))
        {
        }
    
        private static double Method(Base b) 
        {
            // The documentation would state that the method would only be called
            // from Base using "this" as the first argument
            Derived d = (Derived) b;
        }
    }
    


Basically you get the compiler error because you are referencing the instance-method Method without an instance of your class Derived. When calling base, the constructor has not yet finished and you don't have an instance of your class yet. If you made Method static it would work just fine.


Another solution to this is simply to defer the initialization of the delegate to the derived class:

public class Base {
   protected Func<double> DoubleFunc { get; set; }

   protected Base() {
      // defer initialization by not setting DoubleFunc
      // or another possibility is to set it to a dummy function:
      DoubleFunc = () => 0;
   }

   public Base(Func<double> func) {
      DoubleFunc = func;
   }
}

public class Derived : Base {
   public Derived() {
      DoubleFunc = Method;
   }

   public double Method() { return 1.0; }
}


Have you tried making Method() static as the compiler indicates? The problem is that an instance of Derived isn't available until after the constructor has returned so you can't call an instance method on it.


The "workaround" would be to make Method() a static method.

I can't explain the technical reasons why this does not work but essentially you're trying to call a method on an instance which does not yet exist. How could it possibly work?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜