16

あなたは皆これをします:

public void Proc(object parameter)
{
    if (parameter == null)
        throw new ArgumentNullException("parameter");

    // Main code.
}

Jon Skeet はかつて、拡張機能を使用してこのチェックを行うことがあると述べたので、次のことを実行できます。

parameter.ThrowIfNull("parameter");

そのため、この拡張機能の 2 つの実装を思いついたのですが、どちらが最適かはわかりません。

初め:

internal static void ThrowIfNull<T>(this T o, string paramName) where T : class
{
    if (o == null)
        throw new ArgumentNullException(paramName);
}

2番:

internal static void ThrowIfNull(this object o, string paramName)
{
    if (o == null)
        throw new ArgumentNullException(paramName);
}

どう思いますか?

4

7 に答える 7

13

Guard私はこれのためにユビキタスクラスに固執する傾向があります:

static class Guard
{
    public static void AgainstNulls(object parameter, string name = null)
    {
        if (parameter == null) 
            throw new ArgumentNullException(name ?? "guarded argument was null");

        Contract.EndContractBlock(); // If you use Code Contracts.
    }
}

Guard.AgainstNulls(parameter, "parameter");

そして、 を拡張することをためらいますobject。さらに、肉眼では、nullオブジェクトのメソッド呼び出しは無意味に見えます (ただし、拡張メソッドに対して null メソッド呼び出しを行うことが完全に有効であることはわかっています)。

どちらが良いかというと、私はどちらも使いません。どちらも無限再帰があります。また、メッセージ パラメーターを保護する必要もありません。オプションで null にします。制約によってブロックされるため、最初のソリューションもNullable<T>タイプをサポートしません。class

私たちのGuardクラスには、Contract.EndContractBlock()必要な「if-then-throw」構造に適合するため、Code Contracts を有効にすることを決定したときの呼び出しもあります。

これは、 PostSharp アスペクトの最適な候補でもあります。

于 2012-07-17T12:09:09.483 に答える
5

私は使用しますinternal static void ThrowIfNull<T>(this T o, string paramName) where T : classinternal static void ThrowIfNull(this object o, string paramName)ボクシングをするかもしれないので使いません。

于 2012-07-17T12:16:34.907 に答える
4

パラメータ名のハードコーディングを避けるために、この方法を使用します。明日は変わる可能性があり、それからあなたはより多くの仕事をします:

public static void ThrowIfNull<T>(this T item) where T : class
{
    var param = typeof(T).GetProperties()[0];
    if (param.GetValue(item, null) == null)
        throw new ArgumentNullException(param.Name);
}

そしてそれを呼んでください:

public void Proc(object parameter)
{
    new { parameter }.ThrowIfNull(); //you have to call it this way.

    // Main code.
}

パフォーマンスへの影響はごくわずかであり(私の平凡なコンピューターでは、25ミリ秒未満で100000回実行されました)、通常見られる式ベースのアプローチよりもはるかに高速です。

ThrowIfNull(() => resource);

ここでそのようなものの1つ。しかし、それほど多くのヒットを買う余裕がない場合は、これを使用しないでください。

これをオブジェクトのプロパティに拡張することもできます。

new { myClass.MyProperty1 }.ThrowIfNull();

プロパティ名は実行時に変更されないため、プロパティ値をキャッシュしてパフォーマンスをさらに向上させることができます。

この質問をさらに参照してください:実行時にパラメーター名を解決する

于 2013-02-03T22:07:48.557 に答える
0

式ツリーの使用についてはどうですか ( Visual Studio Magazineから):

using System;
using System.Linq.Expressions;
namespace Validation
{
   public static class Validator
   {
     public static void ThrowIfNull(Expression<Func<object>> expression)
     {
       var body = expression.Body as MemberExpression;
       if( body == null)
       {
         throw new ArgumentException(
           "expected property or field expression.");
       }
       var compiled = expression.Compile();
       var value = compiled();
       if( value == null)
       {
         throw new ArgumentNullException(body.Member.Name);
       }
     }
     public static void ThrowIfNullOrEmpty(Expression<Func<String>> expression)  
     {
        var body = expression.Body as MemberExpression;
        if (body == null)
        {
          throw new ArgumentException(
            "expected property or field expression.");
        }
        var compiled = expression.Compile();
        var value = compiled();
        if (String.IsNullOrEmpty(value))
        {
          throw new ArgumentException(
            "String is null or empty", body.Member.Name);
        }
      }
   }

}

次のように使用します。

public void Proc(object parameter1, object parameter2, string string1)
{
    Validator.ThrowIfNull(() => parameter1);
    Validator.ThrowIfNull(() => parameter2);
    Validator.ThrowIfNullOrEmpty(() => string1);
    // Main code.
}
于 2017-02-07T11:10:05.120 に答える
-1

2つ目は、同じものを処理するためのよりエレガントな方法のようです。この場合、すべての管理対象オブジェクトに制限を設けることができます。

internal static void ThrowIfNull(this object o, string paramName)
{
       if (o == null)
        throw new ArgumentNullException(paramName);
}
于 2012-07-17T12:10:10.370 に答える