c#委托和抽象类

Ber*_*Cim 6 c#

我目前在2个抽象类中有2个具体方法.一个类包含当前方法,而另一个类包含遗留方法.例如

// 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
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望相应的方法在应用程序的相对场景中运行.我打算写一个代表来处理这个问题.我的想法是,我可以调用委托并在其中编写逻辑来处理调用哪个方法,具体取决于调用它的类/项目(至少我认为委托的用途以及如何使用它们).

但是,我对该主题有一些疑问(经过一些谷歌搜索):

1)是否可以让代理知道位于不同类中的2个(或更多)方法?2)是否可以使一个委托产生抽象类(如上面的代码)?(我的猜测是否定的,因为委托创建了传入类的具体实现)3)我试着为上面的代码编写一个委托.但我在技术上受到挑战:

    public delegate List<BaseNode> GetAllNodesDelegate(int k);
    GetAllNodesDelegate del = new GetAllNodesDelegate(ClassCurrent<BaseNode>.GetAllRootNodes);
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

An object reference is required for the non-static field, method, property ClassCurrent<BaseNode>.GetAllRootNodes(int)
Run Code Online (Sandbox Code Playgroud)

我可能误解了一些东西......但如果我必须在调用类中手动声明一个委托,并且如上所述手动传递函数,那么我开始质疑委托是否是处理我的问题的好方法.

谢谢.

Dan*_*ker 9

你试图使用委托的方式(用它来构造它们new,声明一个命名的委托类型)表明你正在使用C#1.如果你实际上使用的是C#3,那么它就容易多了.

首先,你的代表类型:

public delegate List<BaseNode> GetAllNodesDelegate(int k);
Run Code Online (Sandbox Code Playgroud)

已经存在.只是:

Func<int, List<BaseNode>>
Run Code Online (Sandbox Code Playgroud)

所以你不需要声明自己的版本.

其次,您应该将委托视为只有一个方法的接口,并且您可以动态"实现"它,而无需编写命名类.只需编写一个lambda,或直接指定一个方法名称.

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;
    };
Run Code Online (Sandbox Code Playgroud)

lambda就是这种形式(arguments) => { body; }.参数以逗号分隔.如果只有一个,则可以省略括号.如果没有参数,请放一对空括号:().如果正文只有一个语句,则可以省略大括号.如果它只是一个表达式,则可以省略大括号和return关键字.在正文中,您可以参考封闭范围内的任何变量和方法(除了ref/ out参数到封闭方法).

几乎从来没有必要使用new创建委托实例.并且很少需要声明自定义委托类型.使用Func的返回值的代表和Action对返回的代表void.

每当你需要传递的东西就像一个带有一个方法的对象(无论是接口还是类),然后使用委托,你就能避免很多混乱.

特别是,避免使用一种方法定义接口.它只是意味着不是能够编写lambda来实现该方法,而是必须为每个不同的实现声明一个单独的命名类,其模式如下:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

lambda有效地为您完成所有这些工作,从您的代码中消除了这些机械模式.你只是说:

() => /* same code as in TheOneMethod */
Run Code Online (Sandbox Code Playgroud)

它还具有可以更新封闭范围中的变量的优点,因为您可以直接引用它们(而不是使用复制到类的字段中的值).如果您不想修改值,有时这可能是一个缺点.

  • 委托比函数指针更强大,因为它们是"一流的方法"并具有闭包,但这只允许你以多态方式传递它们,并且不会像上面的注释那样消除设置它的复杂性. (2认同)