58

好奇心/利便性のためだけに:C#は、私が知っている2つのクールな条件式機能を提供します。

string trimmed = (input == null) ? null : input.Trim();

string trimmed = (input ?? "").Trim();

私は非常に頻繁に直面する状況のために別のそのような表現を逃します:

入力参照がnullの場合、出力はnullである必要があります。それ以外の場合、出力は入力オブジェクトのメソッドまたはプロパティにアクセスした結果である必要があります。

私は最初の例でそれを正確に実行しましたが、(input == null) ? null : input.Trim()非常に冗長で読みにくいです。

この場合の別の条件式はありますか、それとも??演算子をエレガントに使用できますか?

4

6 に答える 6

50

Groovyのnullセーフ間接参照演算子のようなものですか?

string zipCode = customer?.Address?.ZipCode;

C#チームがこれを調べたところ、問題の詳細については聞いたことがありませんが、エレガントに設計するのは思ったほど簡単ではないことがわかりました。

現時点では、その言語にそのようなものはないと思います。恐れています...そして、その計画については聞いたことがありませんが、それがいつか起こらないとは限りません。

編集:「null条件演算子」としてC#6の一部になります。

于 2010-11-22T10:07:53.673 に答える
10

http://qualityofdata.com/2011/01/27/nullsafe-dereference-operator-in-c/で説明されているように、カスタムNullifyクラスまたは拡張メソッドのいずれかを選択できます。NullSafe

使用法は次のとおりです。

//Groovy:
bossName = Employee?.Supervisor?.Manager?.Boss?.Name

//C# Option 1:
bossName = Nullify.Get(Employee, e => e.Supervisor, s => s.Manager,
                       m => m.Boss, b => b.Name);
//C# Option 2:
bossName = Employee.NullSafe( e => e.Supervisor ).NullSafe( s => s.Boss )
                      .NullSafe( b => b.Name );
于 2011-01-31T05:38:29.753 に答える
9

現在、拡張メソッドを作成できるのは、繰り返したくない場合のみです。恐れ入ります。

public static string NullableTrim(this string s)
{
   return s == null ? null : s.Trim();
}
于 2010-11-22T10:12:09.713 に答える
8

回避策として、多分モナドに基づくこれを使用することができます。

public static Tout IfNotNull<Tin, Tout>(this Tin instance, Func<Tin, Tout> Output)
{
    if (instance == null)
        return default(Tout);
    else
        return Output(instance);
}

このように使用します。

int result = objectInstance.IfNotNull(r => 5);
var result = objectInstance.IfNotNull(r => r.DoSomething());
于 2010-11-22T10:45:41.453 に答える
6

組み込みのものは何もありませんが、必要に応じて拡張メソッドですべてをまとめることができます(おそらく気にしないでしょうが)。

この特定の例の場合:

string trimmed = input.NullSafeTrim();

// ...

public static class StringExtensions
{
    public static string NullSafeTrim(this string source)
    {
        if (source == null)
            return source;    // or return an empty string if you prefer

        return source.Trim();
    }
}

または、より汎用的なバージョン:

string trimmed = input.IfNotNull(s => s.Trim());

// ...

public static class YourExtensions
{
    public static TResult IfNotNull<TSource, TResult>(
        this TSource source, Func<TSource, TResult> func)
    {
        if (func == null)
            throw new ArgumentNullException("func");

        if (source == null)
            return source;

        return func(source);
    }
}
于 2010-11-22T10:12:53.457 に答える
4

私はいくつかの小さな拡張メソッドを書いたのと同じ問題を抱えていました:

public static TResult WhenNotNull<T, TResult>(
    this T subject, 
    Func<T, TResult> expression)
    where T : class
{
    if (subject == null) return default(TResult);
    return expression(subject);
}

public static TResult WhenNotNull<T, TResult>(
    this T subject, Func<T, TResult> expression,
    TResult defaultValue)
    where T : class
{
    if (subject == null) return defaultValue;
    return expression(subject);
}

public static void WhenNotNull<T>(this T subject, Action<T> expression)
    where T : class
{
    if (subject != null)
    {
        expression(subject);
    }
}

このように使用します。

string str = null;
return str.WhenNotNull(x => x.Length);

また

IEnumerable<object> list;
return list.FirstOrDefault().WhenNotNull(x => x.id, -1);

また

object obj;
IOptionalStuff optional = obj as IOptionalStuff;
optional.WhenNotNull(x => x.Do());

null許容型のオーバーロードもあります。

于 2010-11-22T10:19:19.100 に答える