在C#中邪恶使用Maybe monad和扩展方法? [英] Evil use of Maybe monad and extension methods in C#?

查看:144
本文介绍了在C#中邪恶使用Maybe monad和扩展方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑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.

  1. 有些人坚持认为,如果扩展方法的this参数为null,则该扩展方法应引发异常.我不同意方法名称是否清楚.

  1. Some people are adamant that an extension method should throw an exception if its this parameter is null. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆