1

クラスの特定のインスタンスが null にならないようにするにはどうすればよいですか? 誰かが私に Debug.Assert() を使用するように言いましたが、そうすることで、コードがデバッグモードで機能することだけを保証しますが、リリースでも is-never-null 条件を保証したいと考えています。

たとえば、過去に次のようなコードを書きました。

public string MyString
{
get
{
    if(instance1.property1.Equals("bla"))
    {
        return bla; 
    }
}
}

ただし、instance1 が null の場合、これは例外をスローします。このような間違いを犯したり、将来的にそのような例外を生成したりすることは避けたいと思います。

ありがとう、


問題を説明する以下の特定の例を参照してください。

サーバーからの応答に基づいてユーザーを認証する方法があります。メソッドは次のとおりです。

        /// <summary>
    /// attempts authentication for current user
    /// </summary>
    /// <returns></returns>
    public AuthResult CheckUser()
    {
        WebRequest request = WebRequest.Create(GetServerURI);
        request.Method = "POST";
        request.ContentType = "application/x-www-form-urlencoded";

        string postdata = "data=" + HttpUtility.UrlEncode(SerializeAuth());
        byte[] arr = Utils.AppDefaultEncoding.GetBytes(postdata);
        request.ContentLength = arr.Length;
        request.Timeout = Convert.ToInt32(TimeUtils.GetMiliseconds(10, TimeUtils.TimeSelect.Seconds));

        Stream strToWrite = request.GetRequestStream();
        strToWrite.Write(arr, 0, arr.Length);

        WebResponse response = request.GetResponse();
        using (Stream dataFromResponse = response.GetResponseStream())
        {
            using (StreamReader reader = new StreamReader(dataFromResponse))
            {
                string readObj = reader.ReadToEnd();
                return DeserializeAuth(readObj);
            }
        }
    }

このメソッドを呼び出すために、私は使用します

_authenticationResult = authObj.CheckUser();

私はまた、とりわけ、このプロパティを持っています

        public ResultType AuthResult
    {
        get
        {
            if (_authenticationResult.auth == "1")
                return ResultType.Success;
            if (_authenticationResult.auth == "0")
                return ResultType.FailAccountExpired;
            if (_authenticationResult.auth == "-1")
                return ResultType.FailWrongUsernameOrPassword;
            if (_authenticationResult.auth == "-2")
                return ResultType.Banned;


            return ResultType.NoAuthDone;
        }
    }

public enum ResultType { Success, FailWrongUsernameOrPassword, FailAccountExpired, NoAuthDone, Banned }

何が起こったのかというと、_authenticationResult が 1 回 null で、プロパティ AuthResult が「null.auth」の試行時に nullref をスローしたことです。どうすれば(おそらくCheckUser()メソッド内で)nullを返さないことを確認できますか?

アプリをデバッグしたとき、それは起こりませんでした。しかし本番環境では、サーバーがタイムアウトしたときに、メソッドが null を返すことがありました。

ありがとう、

4

6 に答える 6

6

instance1、およびその後property1インスタンス化される方法を理解し、null にならないような方法でのみインスタンス化する必要があると思います。これは通常、構築時に引数をチェックすることによって行われます。たとえば、次のようになります。

public instance1(string property1)
{
    if (property1 == null) throw new ArgumentNullException("property1");

    this.property1 = property1;
}

無効な状態で存在できないような方法で型を作成すると、依存するコードがnull値に失敗しないことが保証されます。

そうでなければ、より具体的なアドバイスを提供するために、あなたが行っていることのより完全な例を見る必要があります.

考慮すべきもう1つのことは、クラスが存在できる状態が操作の必須状態であるか、操作のオプション状態であるかです。つまり、クラスが動作するために必要なメンバーは何か、またクラスが常に必要な状態になるように設計するように努める必要があります。次に例を示します。

public class Person
{
  public Person(string forename, string surname)
  {
    if (forename == null) throw new ArgumentNullException("forename");
    if (surname == null) throw new ArgumentNullException("surname");

    Forename = forename;
    Surname = surname;
  }

  public string Forename { get; private set; }
  public string Surname { get; private set; }
}

私の例の型では、 myForenameSurnamevalue に null 以外の値が必要です。これは私のコンストラクターによって強制されます... 私のPerson型は null 値でインスタンス化することはできません (ただし、おそらく空の値も同様に悪いため、適切なものをチェックIsNullOrWhiteSpaceしてスローすることArgumentExceptionがルートですが、シンプルに保ちましょう)。

オプションのフィールドを導入する場合は、Personインスタンスの状態を変更できるようにします。たとえば、セッターを指定します。

public class Person
{
  public Person(string forename, string surname)
  {
    if (forename == null) throw new ArgumentNullException("forename");
    if (surname == null) throw new ArgumentNullException("surname");

    Forename = forename;
    Surname = surname;
  }

  public string Forename { get; private set; }
  public string Surname { get; private set; }

  public string Initial { get; set; }
}

私のPersonタイプは、操作に必要なフィールドを引き続き強制しますが、オプションのフィールドを導入します。次に、これらのメンバーを使用する操作を実行するときに、これを考慮する必要があります。

public override ToString()
{
  return Forename + (Initial == null ? String.Empty : " " + Initial) + " " + Surname;
}

(ただし、これは の最大の例ではありませんToString)。

于 2011-11-08T14:32:47.153 に答える
2

以下を使用できます。

if ( instance1 != null && instance1.property1.Equals("bla")){
   // Your code 
 } 
于 2011-11-08T14:31:02.383 に答える
1

一般に、人々はこの状況に 3 つの方法のいずれかで対処します。最悪の方法 (私の意見では) は、参照するすべての参照について偏執的になり、常に null に対してテストし、null に遭遇した場合は「何か」を実行することです。このようなアプローチの問題点は、コール ツリーの奥深くにいることが多いため、実行する「何か」(「妥当な」デフォルト値を返すなど) がレイヤリング違反になる可能性があるだけでなく、しかし、問題に直面させるのではなく、問題を紙に書き留める傾向があります。このような場合、中途半端に続行しようとするよりも、実際には NulLReferenceException をスローする方がよいでしょう。

より賢明なことは、参照がnullになることがないことがコンテキストから明らかないくつかの場合を除いて、参照がnullにならないコーディング規則を確立することです。さらに、可能な限り、クラスを不変またはほとんど不変にして、すべての不変条件をコンストラクターで実行し、コードの残りの部分を存続させることができます。たとえば、次のように書きます。

public class Person {
  private readonly string firstName;
  private readonly string lastName;
  private readonly Nubbin optionalNubbin;
}

...オプションのNubbinがnullである可能性があることは、名前から明らかです。

最後の最も根本的なアプローチは、null を許可しないコードを記述することです。Nullable<T> のデュアルを発明できます。つまり、次のようになります。

public struct NonNullable<T> {
  ...
}

実装はいくつかの異なる方法 (明示的な Value プロパティを使用するか、おそらく演算子のオーバーロードを使用することによって) で機能しますが、いずれにせよ、NonNullable の仕事は、誰かがそれを null に設定できないようにすることです。

于 2011-11-08T15:16:38.330 に答える
1

個人的には、??を使用します。演算子(が文字列であると仮定property1)

public string MyString
{
    get { instance1.property1 ?? "Default value"; }
}
于 2011-11-08T14:39:59.670 に答える
0

instance1.property1null であってはならないため、適切に初期化する方法があるかどうかを確認し、誰かが null に設定しようとするとスローさArgumentNullExceptionれます。

例:

public string Property1
{
    set 
    {
      if(value == null)
      {
        throw new ArgumentNullException();
      } 
      instance1.property1 = value;
    }
}
于 2011-11-08T14:32:48.370 に答える
0

以下のようなことができます。

public string MyString
{
    get
    {
        if(instance!=null && instance1.property1.Equals("bla"))
        {
            return "bla"; 
        }
        else 
        {
            return String.Empty; 
        }
    }
}

これは基本的に、インスタンスが null かどうかを最初にチェックします。

于 2011-11-08T14:41:30.960 に答える