edit 2015この質問とその回答は、もはや関連性がありません。null伝播演算子(?.)を持つC#6の出現前に質問されました。これにより、この質問とその後の回答で説明されているハックな回避策が不要になります。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;
}
}
Maybe<T> モナド、または何らかの「if not null」拡張メソッドの使用について、StackOverflow でいくつかの議論がありました。
試み #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」とラムダが繰り返されると、構文が少し乱雑になります。私は今、このデザインを検討しています:
試行 #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);
}
}
私の質問は次のとおりです:これは拡張メソッドの悪用ですか? 古い通常のヌルチェックよりも優れていますか?