c# delegate and abstract class

c#

Solution

The way you're attempting to use delegates (constructing them with `new`, declaring a named delegate type) suggests that you're using C# 1. If you're actually using C# 3, it's much easier than that.

Firstly, your delegate type:

public delegate List<BaseNode> GetAllNodesDelegate(int k);

Already exists. It's just:

Func<int, List<BaseNode>>

So you don't need to declare your own version of it.

Secondly, you should think of a delegate as being like an interface with only one method in it, and you can "implement" it on the fly, without having to write a named class. Just write a lambda, or assign a method name directly.

Func<int, List<BaseNode>> getNodesFromInt;

// just assign a compatible method directly
getNodesFromInt = DoSomethingWithArgAndReturnList;

// or bind extra arguments to an incompatible method:
getNodesFromInt = arg => MakeList(arg, "anotherArgument");

// or write the whole thing specially:
getNodesFromInt = arg =>
    {
        var result = new List<BaseNode>();
        result.Add(new BaseNode());
        return result;
    };

A lambda is of the form `(arguments) => { body; }`. The arguments are comma-separated. If there's only one, you can omit the parentheses. If it takes no parameters, put a pair of empty parentheses: `()`. If the body is only one statement long, you can omit the braces. If it's just a single expression, you can omit the braces and the `return` keyword. In the body, you can refer to practically any variables and methods from the enclosing scope (apart from `ref`/`out` parameters to the enclosing method).

There's almost never any need to use `new` to create a delegate instance. And rarely a need to declare custom delegate types. Use `Func` for delegates that return a value and `Action` for delegates that return `void`.

Whenever the thing you need to pass around is like an object with one method (whether an interface or a class), then use a delegate instead, and you'll be able to avoid a lot of mess.

In particular, avoid defining interfaces with one method. It will just mean that instead of being able to write a lambda to implement that method, you'll have to declare a separate named class for each different implementation, with the pattern:

class Impl : IOneMethod
{
    // a bunch of fields

    public Impl(a bunch of parameters)
    {
        // assign all the parameters to their fields
    }

    public void TheOneMethod()
    {
        // make use of the fields
    }
}

A lambda effectively does all that for you, eliminating such mechanical patterns from your code. You just say:

() => /* same code as in TheOneMethod */

It also has the advantage that you can update variables in the enclosing scope, because you can refer directly to them (instead of working with values copied into fields of a class). Sometimes this can be a disadvantage, if you don't want to modify the values.

Problem

I currently have 2 concrete methods in 2 abstract classes. One class contains the current method, while the other contains the legacy method. E.g. ``` // Class #1 public abstract class ClassCurrent<T> : BaseClass<T> where T : BaseNode, new() { public List<T> GetAllRootNodes(int i) { //some code } } // Class #2 public abstract class MyClassLegacy<T> : BaseClass<T> where T : BaseNode, new() { public List<T> GetAllLeafNodes(int j) { //some code } } ``` I want the corresponding method to run in their relative scenarios in the app. I'm planning to write a delegate to handle this. The idea is that I can just call the delegate and write logic in it to handle which method to call depending on which class/project it is called from (at least thats what I think delegates are for and how they are used). However, I have some questions on that topic (after some googling): 1) Is it possible to have a delegate that knows the 2 (or more) methods that reside in different classes? 2) Is it possible to make a delegate that spawns off abstract classes (like from the above code)? (My guess is a no, since delegates create concrete implementation of the passed-in classes) 3) I tried to write a delegate for the above code. But I'm being technically challenged: ``` public delegate List<BaseNode> GetAllNodesDelegate(int k); GetAllNodesDelegate del = new GetAllNodesDelegate(ClassCurrent<BaseNode>.GetAllRootNodes); ``` I got the following error: ``` An object reference is required for the non-static field, method, property ClassCurrent<BaseNode>.GetAllRootNodes(int) ``` I might have misunderstood something... but if I have to manually declare a delegate at the calling class, AND to pass in the function manually as above, then I'm starting to question whether delegate is a good way to handle my problem. Thanks.

Original source