可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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?
回答1:
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>
.
回答2:
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)))
回答3:
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))
回答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)
回答5:
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.
回答6:
Use a nullable:
ProportionPoint? p1 = null;
if (p1 == null) ...
or
if (!p1.HasValue) ...
回答7:
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.
回答8:
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.
回答9:
Structure variables cannot be null, one option would be to declare it as nullable.
回答10:
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;
}
}