c# - 配列 - 構造体がインスタンス化されているかどうかを確認する方法はありますか?




オブジェクトの初期化を簡略化できます (7)

私は構造体を(この質問の目的のために)ほとんどのPointの組み込み型を模倣している。

それを使用する前にインスタンス化されていることを確認する必要があります。 それがPointだったとき、私はこれをすることができました:

if (this.p == null)

しかし、それは今、次のエラーを生成します:

演算子 '=='は、 'ProportionPoint'および '<null>'タイプのオペランドには適用できません

私の構造体をnullと比較するにはどうすればよいですか? インスタンス化をチェックする別の方法がありますか?


pはnullでない構造体なので、それをデフォルト値と比較する必要があります。 あなたの価値とdafault値の間の同等性をチェックするために。 ==を使用すると、

cannot be applied to operands of type 'ProportionPoint' and 'ProportionPoint' error

構造体はデフォルトで==の実装を取得しないためです。 だから、あなたは以下のようにあなたの構造体に==と!=演算子をオーバーロードする必要があります:

public static bool operator ==(firstOperand op1,  secondOperand2 op2) 
{
    return op1.Equals(op2);
}

public static bool operator !=(firstOperand op1,  secondOperand2 op2) 
{
   return !op1.Equals(op2);
}

その後 :

if (this.p == default(ProportionPoint))

別のオプションは、Equalsを直接使用することです。

f (this.p.Equals.default(ProportionPoint))

structは値型です - 決してnullです。

構造体のデフォルト値(ゼロなど)であるdefault(ProportionPoint)に対してチェックすることができdefault(ProportionPoint) 。 しかし、ポイントについては、デフォルト値である原点も「有効な」値である可能性があります。

代わりにNullable<ProportionPoint>使用できます。


その型の0または1つのインスタンスへの参照である参照型の変数または値とは異なり、構造体変数または値構造体インスタンスです。 1つのコードブロックが{Point myPoint; ...} {Point myPoint; ...} 、ブロック内の何もMyPoint閉じることはありません(ブロック内にyield returnがあるとき、またはラムダまたは匿名メソッドが囲みブロックの変数を使用するときに終了します)、 Pointインスタンスが入ります実行前のある時点での存在がブロックに入り、実行がブロックを離れるといつでも存在する可能性があります。 構造型変数を使用できるあらゆるコンテキストでは、構造体が存在します。

すべての構造体型が何もしないデフォルトのコンストラクタを持つとみなされる理由は、構造体型が暗黙的に存在するためです。 Point[] myPoints = new Point[100];ようなステートメントを実行すると、 Point[] myPoints = new Point[100]; 100個のPoint構造体のゼロ充填配列を作成します。 このプロセスでは、 100ゼロ充填点インスタンスが即座に存在します。 C ++では、ある型にコンストラクタがある場合、その型の配列を作成すると、その配列のすべての要素に対して順番にコンストラクタが呼び出されます。 要素の作成中に例外がスローされた場合、コンパイラ生成コードは、配列自体が蒸発する前に正常に作成されたすべての要素に対して確定的デストラクタを実行します。 これは非常に強力な機能ですが、.netの中に含めれば、Frameworkがかなり複雑になります。


ヌル可能:

ProportionPoint? p1 = null;
if (p1 == null) ...

または

if (!p1.HasValue) ...

構造体はnullにはできませんが、実際に構造体のデフォルトに相当する値を任意の点に格納したい場合は、構造体をデフォルトと照合して回避することで偽のネガティブな値を与えることができます。

(たとえば、 (0,0,0)の値を持つ構造体は、変更されていないデフォルトでも、3D空間に原点を格納することもできます)。

この偽のネガティブな問題を回避するもう1つのアプローチは、データが実際にそこに格納されているかどうかを追跡するために、構造体に別のプロパティ(たとえばboolまたはint)を追加することだけです。 次に、実際のデータでこの値をtrue / 1に設定して構造体を初期化するコンストラクタを用意します。 デフォルトの構造体では、この値はfalse / 0になりdefault(MyStruct)チェックすると、それに格納されている他のすべてのデータがデフォルト値と一致しても、

public Struct MyStruct { 
    public float x { get; private set; }
    public bool initialized { get; private set; }

    public MyStruct(float _x){
        x=_x;
        initialized = true;
    }
}

構造体は値型であり、参照型とは逆にnullになることはありません。 あなたはデフォルト値をチェックすることができます:

if (this.p.Equals(default(ProportionPoint)))

私は構造体だけで動作する拡張メソッドを作った:

public static bool IsNull<T>(this T source) where T:struct
{
  return source.Equals(default(T));
}

呼び出し規約:

if(myStruct.IsNull())
  DoSomething();

私はそれが本当にnullかどうかを確認していないことを理解していnull 。 しかし、 IsEmptyIsDefaultようなもっと正確な名前を6ヵ月間に渡すと、それがそこにあるのを忘れてしまい、利用可能なメソッドのリストを見てもそれを選ぶことはできません。 技術的にはヌルチェックではありません。 概念的にはそうです。







null