当前位置:  开发笔记 > 编程语言 > 正文

这种C#扩展方法是不纯的,如果是这样,代码不好?

如何解决《这种C#扩展方法是不纯的,如果是这样,代码不好?》经验,为你挑选了2个好方法。

我正在学习函数编程,我想知道:

1)如果我的ForEach扩展方法是纯粹的?我打电话的方式似乎违反了"不要把对象弄得乱七八糟",对吧?

public static void ForEach(this IEnumerable source, Action action)
{
  foreach ( var item in source )
     action(item);
}


static void Main(string[] args)
{
    List cats = new List()
    {
        new Cat{ Purring=true,Name="Marcus",Age=10},
        new Cat{ Purring=false, Name="Fuzzbucket",Age=25 },
        new Cat{ Purring=false, Name="Beanhead",Age=9 },
        new Cat{Purring=true,Name="Doofus",Age=3}
    };


    cats.Where(x=>x.Purring==true).ForEach(x =>
    {
        Console.WriteLine("{0} is a purring cat... purr!", x.Name);
    });

    // *************************************************
    //  Does this code make the extension method impure?
    // *************************************************
    cats.Where(x => x.Purring == false).ForEach(x =>
    {
        x.Purring = true; // purr,baby
    });

    // all the cats now purr
    cats.Where(x=>x.Purring==true).ForEach(x =>
    {
        Console.WriteLine("{0} is a purring cat... purr!", x.Name);
    });
}

public class Cat {
        public bool Purring;
        public string Name;
        public int Age;
}

2)如果不纯,那么代码是不是很糟糕?我个人认为它使代码看起来比旧的更清晰foreach ( var item in items) { blah; },但我担心,因为它可能是不纯的,它可能会弄得一团糟.

3)如果它返回IEnumerable而不是代码是坏代码void吗?我会说,只要它是不纯的,是的,这将是非常糟糕的代码,因为它会鼓励链接一些会修改链的东西.例如,这是不好的代码?

// possibly bad extension
public static IEnumerable ForEach(this IEnumerable source, Action action)
{
    foreach ( var item in source )
        action(item);

    return source;

}

MichaelGG.. 12

杂质并不一定意味着糟糕的代码.许多人发现使用副作用解决问题很容易和有用.关键是首先要知道如何以纯粹的方式做到这一点,所以你会知道什么时候杂质是合适的:).

.NET在类型系统中没有纯度的概念,因此接受任意委托的"纯粹"方法总是不纯的,这取决于它的调用方式.例如,"Where",又名"filter",通常被认为是纯函数,因为它不会修改其参数或修改全局状态.

但是,没有什么可以阻止你将这些代码放在Where的参数中.例如:

things.Where(x => { Console.WriteLine("um?"); 
                    return true; })
      .Count();

所以这肯定是Where的不纯用法.Enumerables可以在迭代时做任何他们想做的事.

你的代码不好吗?没有.使用foreach循环就像"不纯"一样 - 你仍在修改源对象.我一直在编写这样的代码.将一些选择,过滤器等链接在一起,然后在其上执行ForEach以调用某些工作.你是对的,它更干净,更容易.

示例:ObservableCollection.由于某种原因,它没有AddRange方法.所以,如果我想添加一些东西,我该怎么办?

foreach(var x in things.Where(y => y.Foo > 0)) { collection.Add(x)); } 

要么

things.Where(x => x.Foo > 0).ForEach(collection.Add);

我更喜欢第二个.至少,我看不出它如何被解释为比第一种方式更糟糕.

什么时候代码不好?当它在一个不期望的地方执行副作用代码时.这是我使用Where的第一个例子的情况.即便如此,有时候范围非常有限且使用情况很明显.

链接ForEach

我编写的代码就是这样做的.为了避免混淆,我会给它另一个名字.主要的困惑是"这是立即评估还是懒惰?".ForEach意味着它将立即执行一个循环.但是返回IEnumerable的东西意味着将根据需要处理这些项目.所以我建议给它另一个名字("Process","ModifySeq","OnEach"......类似的东西),并让它变得懒惰:

public static IEnumerable OnEach(this IEnumerable src, Action f) {
  foreach(var x in src) {
    f(x);
    yield return x;
  }
}


Brian.. 6

它不纯,因为它可以称为不纯的方法.我认为通过典型的定义,纯度是一个传递闭包 - 只有当它调用的所有函数(直接或间接)都是纯粹的,或者如果这些函数的效果被封装时(例如它们只是改变非转义),函数才是纯的.局部变量).



1> MichaelGG..:

杂质并不一定意味着糟糕的代码.许多人发现使用副作用解决问题很容易和有用.关键是首先要知道如何以纯粹的方式做到这一点,所以你会知道什么时候杂质是合适的:).

.NET在类型系统中没有纯度的概念,因此接受任意委托的"纯粹"方法总是不纯的,这取决于它的调用方式.例如,"Where",又名"filter",通常被认为是纯函数,因为它不会修改其参数或修改全局状态.

但是,没有什么可以阻止你将这些代码放在Where的参数中.例如:

things.Where(x => { Console.WriteLine("um?"); 
                    return true; })
      .Count();

所以这肯定是Where的不纯用法.Enumerables可以在迭代时做任何他们想做的事.

你的代码不好吗?没有.使用foreach循环就像"不纯"一样 - 你仍在修改源对象.我一直在编写这样的代码.将一些选择,过滤器等链接在一起,然后在其上执行ForEach以调用某些工作.你是对的,它更干净,更容易.

示例:ObservableCollection.由于某种原因,它没有AddRange方法.所以,如果我想添加一些东西,我该怎么办?

foreach(var x in things.Where(y => y.Foo > 0)) { collection.Add(x)); } 

要么

things.Where(x => x.Foo > 0).ForEach(collection.Add);

我更喜欢第二个.至少,我看不出它如何被解释为比第一种方式更糟糕.

什么时候代码不好?当它在一个不期望的地方执行副作用代码时.这是我使用Where的第一个例子的情况.即便如此,有时候范围非常有限且使用情况很明显.

链接ForEach

我编写的代码就是这样做的.为了避免混淆,我会给它另一个名字.主要的困惑是"这是立即评估还是懒惰?".ForEach意味着它将立即执行一个循环.但是返回IEnumerable的东西意味着将根据需要处理这些项目.所以我建议给它另一个名字("Process","ModifySeq","OnEach"......类似的东西),并让它变得懒惰:

public static IEnumerable OnEach(this IEnumerable src, Action f) {
  foreach(var x in src) {
    f(x);
    yield return x;
  }
}



2> Brian..:

它不纯,因为它可以称为不纯的方法.我认为通过典型的定义,纯度是一个传递闭包 - 只有当它调用的所有函数(直接或间接)都是纯粹的,或者如果这些函数的效果被封装时(例如它们只是改变非转义),函数才是纯的.局部变量).

推荐阅读
拾味湖
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有