我目前在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)
我可能误解了一些东西......但如果我必须在调用类中手动声明一个委托,并且如上所述手动传递函数,那么我开始质疑委托是否是处理我的问题的好方法.
谢谢.
你试图使用委托的方式(用它来构造它们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)
它还具有可以更新封闭范围中的变量的优点,因为您可以直接引用它们(而不是使用复制到类的字段中的值).如果您不想修改值,有时这可能是一个缺点.