c#函数式编程 Functional Programming in C# [19]

这篇博客探讨了如何将Option类型与IEnumerable接口结合使用,以处理可能缺失的数据。通过将Option视为特殊形式的列表,可以将其转换为IEnumerable并利用其方法。作者提供了将Option重载为IEnumerable的Bind方法,以便在处理例如调查参与者年龄等数据时,能够过滤掉None值并计算平均值。这种方法展示了在实际编程中如何优雅地处理可能存在的空值情况。
摘要由CSDN通过智能技术生成

4.5 结合 Option 和 IEnumerable 与 Bind

  我已经提到,看待 Option 的一种方式是将其作为一个列表的特例,它既可以是空的(None),也可以正好包含一个值(Some)。你甚至可以在代码中表达这一点,把一个Option转换为一个IEnumerable,如下所示:

public struct Option<T>{
	public IEnumerable<T> AsEnumerable()
	{
		if (IsSome) 
			yield return Value;   
	}
}

  如果Option是Some,产生的IEnumerable将产生一个项目;如果是None,它将不产生任何项目。现在你可以访问所有定义在IEnumerable上的扩展方法,如下面的例子:

Some("thing").AsEnumerable().Count() // => 1

  这真的有用吗?在实践中,IEnumerable经常被用来存储数据,而Option则在一个值不存在的时候跳过计算,所以它们的意图通常是不同的。
  然而,在某些情况下,将它们结合起来是很有用的。在有些情况下,你可能会得到一个IEnumerable< Option< T > >,或者反过来说,一个Option<IEnumerable< T >>,而你可能想把它平铺成一个IEnumerable< T >。
  例如,让我们回到调查的例子中,每个参与者被模拟为一个Subject,由于参与者可以选择披露他们的年龄,Subject.Age被模拟为一个Option< Age >:

class Subject {
    public Option < Age > Age { get; set; }
}
IEnumerable < Subject > Population => new [] {
    new Subject { Age = Age.Of(33) }, 
    new Subject {}, //此人没有透露其年龄。
    new Subject { Age = Age.Of(37) },
};

  你把参与者的详细资料存储在一个IEnumerable< Subject >中。现在,假设你需要计算参与者的平均年龄,对于那些选择披露他们年龄的人。你可以怎么做呢?你可以从选择Age的所有值开始:

var optionalAges = Population.Map(p => p.Age);
// => [Some(Age(33)), None, Some(Age(37))]

  如果你用Map来选择接受调查者的年龄,你会得到一个Option列表。 因为一个Option可以被看作是一个列表,所以optionalAges也可以被看作是一个列表。
  为了将这种直觉转化为代码,让我们给Bind添加一些重载,将Option转换为IEnumerable,这样Bind就可以被应用,就好像我们在平铺一个嵌套的IEnumerable:

public static IEnumerable<R> Bind<T, R>
	(this IEnumerable<T> list, Func<T, Option<R>> func)
	=> list.Bind(t => func(t).AsEnumerable());
public static IEnumerable<R> Bind<T, R>
	(this Option<T> opt, Func<T, IEnumerable<R>> func)
	=> opt.AsEnumerable().Bind(func);

  尽管根据FP理论,Bind应该只对一种类型的容器起作用,但是Option总是可以被 "提升 "到更通用的IEnumerable这一事实使得这些重载有效,并且在实践中相当有用:

  • 第一个重载可以用来获得一个IEnumerable< T >,而Map会给你一个IEnumerable<Option< T >>,就像在目前的调查例子中。
  • 第二个重载可以用来获得一个IEnumerable< T >,而Map会给你一个Option<IEnumerable < T > >。

  在调查方案中,我们现在可以用Bind来过滤掉所有的Nones,得到所有实际给出的年龄列表:

var optionalAges = Population.Map(p => p.Age);
// => [Some(Age(33)), None, Some(Age(37))]
var statedAges = Population.Bind(p => p.Age);
// => [Age(33), Age(37)]
var averageAge = statedAges.Map(age => age.Value).Average();
// => 35

  这使得我们可以利用Bind的 "扁平化 "特性来过滤掉所有的None情况。 前面的输出显示了同时调用Map和Bind的结果,以便你可以比较结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Take advantage of the growing trend in functional programming. C# is the number-one language used by .NET developers and one of the most popular programming languages in the world. It has many built-in functional programming features, but most are complex and little understood. With the shift to functional programming increasing at a rapid pace, you need to know how to leverage your existing skills to take advantage of this trend. Functional Programming in C# leads you along a path that begins with the historic value of functional ideas. Inside, C# MVP and functional programming expert Oliver Sturm explains the details of relevant language features in C# and describes theory and practice of using functional techniques in C#, including currying, partial application, composition, memoization, and monads. Next, he provides practical and versatile examples, which combine approaches to solve problems in several different areas, including complex scenarios like concurrency and high-performance calculation frameworks as well as simpler use cases like Web Services and business logic implementation. Shows how C# developers can leverage their existing skills to take advantage of functional programming Uses very little math theory and instead focuses on providing solutions to real development problems with functional programming methods, unlike traditional functional programming titles Includes examples ranging from simple cases to more complex scenarios Let Functional Programming in C# show you how to get in front of the shift toward functional programming.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值