Func <t>作为类成员,访问实例的其他成员</t>

时间:2014-04-19 18:00:19

标签: c# lambda func

我有一个问题,是否可以(如果是,如何)从class代表内部访问Func<T, TResult>成员。

例如,我有以下class

class NinjaTurtle
{
    public string Sound { get; set; }
    public Func<string, string> DoNinjaMove { get; set; }
}

现在我想这样做

NinjaTurtle leonardo = new NinjaTurtle();
leonardo.Sound = "swiishhh!";
leonardo.DoNinjaMove = (move) => {
    if(move == "katana slash") return leonardo.Sound;
    return "zirp zirp zirp";
}

问题是,当我定义回调函数时,如何正确访问属性Sound?从函数外部使用对实例的引用是否可以?当我将对象传递给另一个方法时,或者当这将成为dll的一部分时,这仍然有用吗?我会从dll中的函数返回对象leonardo吗?它能否“继续”序列化/反序列化?

(感谢弗拉基米尔和李,这个问题现在更具体到我想知道的内容。)

3 个答案:

答案 0 :(得分:5)

您可以使用闭包。闭包将是一个匿名委托或lambda表达式,它可以引用外部作用域中的变量,方法,属性,事件或任何东西(哎呀,这是你的情况!)。

leonardo.DoNinjaMove = (move) => {
    // THIS IS VALID! IT'S A CLOSURE! You can access leonardo reference within
    // the closure!!
    if(move == "katana slash") return leonardo.Sound; 
    return "zirp zirp zirp";
}

无论如何,DoNinjaMoveFunc<string, bool>。如果您想返回Sound值,则应将其重构为Func<string, string>

有关闭包如何工作的详细信息以及为什么可以安全地使用外部作用域的引用,可以在StackOverflow中的其他Q&amp; A中找到:

关于在使用附属程序集时使用闭包是否有效......

是的,这没问题。闭包是大多数现代语言拥有的非常有趣的功能,它是包含函数式编程的语言的必备功能。无论如何,这是必备功能! :)

答案 1 :(得分:2)

这将捕获closure中的变量leonardo并且可以正常工作,但我不认为这是一个很好的设计,但如果没有上下文,很难建议不同的东西。

var leonardo = new NinjaTurtle();

leonardo.Sound = "swiishhh!";

leonardo.DoNinjaMove = (move) =>
{
   if (move == "katana slash")
   {
      return leonardo.Sound;
   }
   else
   {
      return "zirp zirp zirp";
   }
}

您可能需要考虑使用Func<NinjaTurtle, String, String>并明确传递乌龟。

leonardo.DoNinjaMove = (turtle, move) =>
{
   if (move == "katana slash")
   {
      return turtle.Sound;
   }
   else
   {
      return "zirp zirp zirp";
   }
}

但这对我来说仍然不是一个令人信服的设计。

答案 2 :(得分:2)

如果您是从Google来的,特别想将Lambda函数编码为在类主体中声明的类成员,请继续阅读...

我通过Google找到了这篇文章,因为我正在寻找一种方法来声明Lambda Func作为类本身的成员方法。您可以在类内部声明一个Func,但是不能在同一行中直接将其分配给它。示例:

public class myClass {
    public Func<string,string> DoNinjaMove;  //Can't declare method body here.
}

解决方案是像这样在类的构造方法中分配Lambda函数主体:

public class myClass {
    public Func<string,string> DoNinjaMove;  //Can't declare method body here.

    public myClass()
    {
        DoNinjaMove = (someString) =>
        {
            //Do something here
            return anotherString;
        }
    }
}

现在DoNinjaMove是myClass的成员,并且它的主体也在myClass内部声明。 DoNinjaMove有权访问myClass的所有成员,并且您可以将DoNinjaMove传递给其他类/对象,以供他们调用。

除非您完全知道自己在做什么,否则我可能不会推荐这种设计模式。在我的情况下,我正在使用的另一个库要求将具有特定输入和返回类型的Lambda函数传递给它,但我需要将该函数成为我自己的类的成员,为了优雅起见,它可以访问类数据封装。这是我想出的解决方案。