C#语法:将委托分配给类,并稍后调用

3

我希望你能帮我翻译一下这段关于C#语法的内容。这里我想将一个任意委托分配给一个类。

我的委托定义如下:

delegate string stringCB(string s);
delegate int intCB(int i);

我有一个类

class run_by_name {
    public string name {get;set;}
    public Delegate method {get;set;}
};

我正在尝试实例化它

 run_by_name myfuc = new run_by_name(){
     name = "my name",
     method = new stringCB(string s) {
         return " testing " + s;
     };
 };

我真的不清楚在有返回类型时如何分配代理。而且,我不确定语法上如何稍后调用该方法。

为什么这样做?好吧,我只是编写了一些代码,遵循我经常在事件处理中使用的模式,我只是创建了一个“对象”,可以将任意函数分配给它,用于定义而非创建的通用事件处理程序。(重要)

此外,欢迎使用代理的替代方案:)

编辑:我可能如何稍后使用它
我还没有写过,但我相当确定我会这样做。

List<run_by_name> callbacks = new List<run_by_name>();
/* lets say this is initialized and filled at this point */

public object FindAndRunCallback(string Name, object input) {
    foreach(var cb in callbacks) {
        if( cb.name == Name )
            return cb.method(input);
    }
    return null;
}

为什么不使用实际事件?请查看 Action<T>Func<T> 及其相关类。 - Daniel A. White
你应该查看 Func - rageit
你需要写成 method = (string s) => (" testing " + s);,而不是 method = new stringCB(string s) { return " testing " + s; }; - Jashaszun
一个人怎样使用Action<T>,这是我的最初尝试,但我遇到了相同类型的语法问题。 - Aage Torleif
顺便提一下:如果你从另一个角度开始,可能会更好——先决定你想要用什么样的可编译语法来调用你的方法,然后再设计你的类……至少考虑展示一下你想要通过名称和参数来调用它们的方式。 - Alexei Levenkov
2个回答

3

以下是使您当前代码正常工作所需的语法:

 method = new stringCB((string s) =>  {
     return " testing " + s;
 })

或者,使用lambda表达式:

 method = new stringCB(s =>" testing " + s)

您稍后可以这样调用该方法:
string result = (string) myfuc.method.DynamicInvoke("hello");

如果不了解您的具体用途,很难推荐其他方法,但我建议至少考虑以下几点:

  • Events: Your description sounds very close to the common pattern for events and event handlers in C#. Your event defines the delegate type that is used to handle it, and code elsewhere can subscribe to that event with methods that match that delegate type. By convention, people usually pass a sender object as the first parameter, and some strongly-typed EventArgs so that subscribers don't have to guess at what data is going to be available when the event fires.
  • Func<> and Action<> variants: As C# has evolved into a more functional language, programmers have trended away from using custom delegate types, and toward using the provided variants of Func<> and Action<>. Since the arguments are strongly-typed still, you get most of the advantages of a compiled language, but use a little "duck typing" for the actual function you pass around.

    For example, you could give your class a generic type based on what types you expect your delegate to deal with:

    class run_by_name<T> {
        public string name {get;set;}
        public Func<T, T> method {get;set;}
    };
    

    Then use it:

    var myfuc = new run_by_name<string>{
        name = "my name",
        method = s =>" testing " + s
    };
    
    string result = myfuc.method("hello");
    
  • dynamic: This keyword allows you to late-bind actions on any object. You lose the advantages of a compiled language, but it improves interoperability with more dynamic languages immensely. For example, an object can be created via JSON, and you can access the properties on it without declaring a special type for that object, just like you can in Javascript.

    For example, if you changed your method declaration to this:

    public dynamic method {get;set;}
    

    Then you could simply say:

    string result = myfuc.method("hello");
    

你还应该解决“如何在以后调用该方法”的问题。 - Jashaszun
这太棒了,绝对解决了我的困惑,也很好知道如何使用像那样的lambda运算符。 - Aage Torleif

2

您有几个选择。 strinCB 构造函数需要一个方法,该方法接受一个字符串参数并返回一个字符串。如果您有现有的方法,则可以将其名称传递给构造函数,或者您可以使用委托语法创建一个匿名方法,如下所示:

method = new stringCB(delegate(string s)
            {
                return " testing " + s;
            })

或者使用lambda表达式:

method = new stringCB(s =>
            {
                return " testing " + s;
            })

那么你可以像这样调用它:myfuc.method.DynamicInvoke(YourParameter);

通常,调用委托的方法非常简单,就像这样:

Func<int, int, int> sum = (x, y) => x + y;

Console.WriteLine(sum(2,3)); // with the name of delegate

Console.WriteLine(sum.Invoke(2,3)); // or using Invoke method

但在这种情况下,您需要使用DynamicInvoke,因为您的属性类型是Delegate

除此之外,.NET Framework还有一些有用的内置委托类型,例如FuncActionPredicate等。只要它们满足您的需求,您就可以使用它们,而不必创建自己的委托。例如,在这种情况下,您可以使用Func<string,string>代替stringCB


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接