41

I have a struct that (for the purposes of this question) pretty much mimics the built in Point type.

I need to check that it has been instantiated before using it. When it was Point, I could do this:

if (this.p == null)

But that now generates the following error:

Operator '==' cannot be applied to operands of type 'ProportionPoint' and '<null>'

How can I compare my struct against null? Is there another way to check for instantiation?

4

10 に答える 10

53

A struct is a value type - it's never null.

You can check against default(ProportionPoint), which is the default value of the struct (e.g. zero). However, for a point, it may be that the default value - the origin - is also a "valid" value.

Instead you could use a Nullable<ProportionPoint>.

于 2012-10-01T12:43:43.470 に答える
27

structs are value types and they can never be null contrary to reference types. You could check against the default value:

if (this.p.Equals(default(ProportionPoint)))
于 2012-10-01T12:42:16.577 に答える
4

A struct can't be null. Its a value type, not a reference type. You need to check against the properties with the default values. Something like:

if(p.X == 0 && p.Y == 0)
于 2012-10-01T12:41:20.473 に答える
4

because p is struct it never be null so you should compare it to it's default value. In order to check equivalence between your value and dafault value. If you use == you will get

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

because structs do not get an implementation of == by default. so you need to overload the == and != operators in your struct like this:

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

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

and then :

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

another option is to use Equals directly:

f (this.p.Equals.default(ProportionPoint))
于 2016-07-15T17:50:25.213 に答える
3

A struct can never be null, so you can't compare it to null. And a struct is always initialized - if not by you, then by the compiler with default values.

于 2012-10-01T12:42:07.613 に答える
3

Use a nullable:

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

or

if (!p1.HasValue) ...
于 2012-10-01T12:45:33.487 に答える
2

I made an extension method that only works with structs:

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

Calling convention:

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

I understand that it isn't really checking if it's null. However, if I gave it a more precise name, like IsEmpty or IsDefault, in six months I would forget it's there and upon seeing the list of methods available not pick it. It's not technically a null check; but conceptually it is.

于 2017-01-28T20:41:18.993 に答える
2

Structs can't be null, but the workaround of checking a struct against its default can give a false negative if you actually want to store values equivalent to the defaults in it at any point.

(For example, a struct with the value (0,0,0) could be an untouched default, or it could be storing the origin point in 3D space.)

Another approach that avoids this false negative issue would be to just add another property to the struct - e.g. a bool or int - to track whether data has actually been stored in it. Then have any constructor that initializes the struct with actual data set this value to true/1. In the default struct, this value will still be false/0, so checking against default(MyStruct) should never give you a false negative even if all other data stored in it matches the default values.

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

    public MyStruct(float _x){
        x=_x;
        initialized = true;
    }
}
于 2017-12-15T18:04:57.120 に答える
1

Unlike a variable or value of a reference type, which is a reference to either zero or one instances of that type, a struct variable or value is a struct instance. If one has a block of code which starts with {Point myPoint; ...}, and nothing in the block closes over MyPoint (closure occurs when there is a yield return within a block, or when a lambda or anonymous method uses a variable from an enclosing block), then an instance of Point will come into existence sometime before execution enters the block, and may cease to exist at any time after execution leaves the block. In any context where one can make use of a struct-type variable, the structure exists.

The reason one all structure types are regarded as having a do-nothing default constructor is that structure types come into existence implicitly. When one performs a statement like Point[] myPoints = new Point[100];, it creates a zero-filled array of 100 Point structures; in the process, 100 zero-filled Point instances instantly come into existence. In C++, if a type has a constructor, creating an array of that type will call the constructor on every element of the array in sequence before any code is given access to the array as a while. If an exception is thrown while constructing any element, compiler-generated code will run the deterministic destructor on every element which had been successfully created before the array itself evaporates. While this is a very powerful feature, including it within .net would have substantially complicated the Framework.

于 2012-10-01T15:03:55.767 に答える
1

You can't check struct on null but you can check on default unitialized value like this:

if (instanceOfYourStruct == default)
于 2019-12-12T20:42:11.630 に答える