编辑 2015这个问题及其答案不再相关。在 C# 6 出现之前就有人问过它,它具有空传播操作符 (?.),它避免了在这个问题和后续答案中讨论的 hacky-workarounds。截至 2015 年,在 C# 中,您现在应该使用 Form.ActiveForm?.ActiveControl?.Name。
我一直在考虑 .NET 中的 null 传播问题,这通常会导致丑陋的重复代码,如下所示:
尝试 #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 的讨论,或者使用某种“if not null”扩展方法:
尝试#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 有点语法混乱。我现在正在考虑这个设计:
尝试 #3,Maybe<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);
}
}
我的问题是:这是对扩展方法的恶意滥用吗?它比旧的通常的空检查更好吗?