在C#中邪恶使用Maybe monad和扩展方法? [英] Evil use of Maybe monad and extension methods in C#?
问题描述
编辑2015 .此问题及其答案不再相关.在C#6问世之前,有人问过这个问题,它有一个无效的传播运算符(?.),它消除了此问题和后续答案中讨论的hacky解决方法.从2015年开始,在C#中,您现在应该使用Form.ActiveForm?.ActiveControl?.Name.
edit 2015 This question and its answers are no longer relevant. It was asked before the advent of C# 6, which has the null propagating opertor (?.), which obviates the hacky-workarounds discussed in this question and subsequent answers. As of 2015, in C# you should now use Form.ActiveForm?.ActiveControl?.Name.
我一直在考虑.NET中的空传播问题,该问题通常会导致类似这样的丑陋重复代码:
I've been thinking about the null propagation problem in .NET, which often leads to ugly, repeated code like this:
尝试#1常规代码:
string activeControlName = null;
var activeForm = Form.ActiveForm;
if (activeForm != null)
{
var activeControl = activeForm.ActiveControl;
if(activeControl != null)
{
activeControlname = activeControl.Name;
}
}
在StackOverflow上有一些关于Maybe< T>的讨论. monad,或使用某种如果不是null"扩展方法:
There have been a few discussions on StackOverflow about a Maybe<T> monad, or using some kind of "if not null" extension method:
尝试#2,扩展方法:
// Usage:
var activeControlName = Form.ActiveForm
.IfNotNull(form => form.ActiveControl)
.IfNotNull(control => control.Name);
// Definition:
public static TReturn IfNotNull<TReturn, T>(T instance, Func<T, TReturn> getter)
where T : class
{
if (instance != null ) return getter(instance);
return null;
}
我认为这更好,但是,重复的"IfNotNull"和lambda有点句法混乱.我现在正在考虑这种设计:
I think this is better, however, there's a bit of syntactic messy-ness with the repeated "IfNotNull" and the lambdas. I'm now considering this design:
尝试#3,可能是< T>使用扩展方法
// Usage:
var activeControlName = (from window in Form.ActiveForm.Maybe()
from control in window.ActiveControl.Maybe()
select control.Name).FirstOrDefault();
// Definition:
public struct Maybe<T> : IEnumerable<T>
where T : class
{
private readonly T instance;
public Maybe(T instance)
{
this.instance = instance;
}
public T Value
{
get { return instance; }
}
public IEnumerator<T> GetEnumerator()
{
return Enumerable.Repeat(instance, instance == null ? 0 : 1).GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
public static class MaybeExtensions
{
public static Maybe<T> Maybe<T>(this T instance)
where T : class
{
return new Maybe<T>(instance);
}
}
我的问题:这是对扩展方法的恶意滥用吗?比以前的常规空值检查好吗?
My question is: is this an evil abuse of extension methods? Is it better than the old usual null checks?
推荐答案
有趣的是,有很多人独立选择名称IfNotNull
,为此在C#中,它必须是最明智的名称! :)
It's interesting that so many people independently pick the name IfNotNull
, for this in C# - it must be the most sensible name possible! :)
我在SO上找到的最早的一个:可能的陷阱使用这种(基于扩展方法的)速记
Earliest one I've found on SO: Possible pitfalls of using this (extension method based) shorthand
我的一个(不了解上述内容):在C#中管道向前移动
My one (in ignorance of the above): Pipe forwards in C#
另一个最近的示例:如何在深Lambda表达式中检查空值?
IfNotNull
扩展方法可能不受欢迎的原因有两个.
There are a couple of reasons why the IfNotNull
extension method may be unpopular.
-
有些人坚持认为,如果扩展方法的
this
参数为null
,则该扩展方法应引发异常.我不同意方法名称是否清楚.
Some people are adamant that an extension method should throw an exception if its
this
parameter isnull
. I disagree if the method name makes it clear.
扩展名适用范围太广,将使自动完成菜单变得混乱.可以通过正确使用命名空间来避免这种情况,这样它们就不会惹恼不需要它们的人.
Extensions that apply too broadly will tend to clutter up the auto-completion menu. This can be avoided by proper use of namespaces so they don't annoy people who don't want them, however.
我也尝试过IEnumerable
方法,就像做一个实验来看看我可以扭曲多少东西来适应Linq关键字一样,但是我认为最终结果比IfNotNull
链接可读性差或原始命令代码.
I've played around with the IEnumerable
approach also, just as an experiment to see how many things I could twist to fit the Linq keywords, but I think the end result is less readable than either the IfNotNull
chaining or the raw imperative code.
我最终得到了一个简单的自包含的Maybe
类,它带有一个静态方法(不是扩展方法),对我来说非常好用.但是,然后,我与一个小团队一起工作,而我的下一个高级同事对函数式编程和lambda等感兴趣,所以他并没有因此而感到失望.
I've ended up with a simple self-contained Maybe
class with one static method (not an extension method) and that works very nicely for me. But then, I work with a small team, and my next most senior colleague is interested in functional programming and lambdas and so on, so he isn't put off by it.
这篇关于在C#中邪恶使用Maybe monad和扩展方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!