我有一个结构(就这个问题而言)几乎模仿了内置Point
类型。
我需要在使用它之前检查它是否已经实例化。当它是时Point
,我可以这样做:
if (this.p == null)
但是现在会产生以下错误:
运算符“==”不能应用于“ProportionPoint”和“<null>”类型的操作数
如何将我的结构与 null 进行比较?还有另一种检查实例化的方法吗?
Astruct
是一种值类型 - 它永远不会为空。
您可以检查default(ProportionPoint)
,这是结构的默认值(例如零)。但是,对于某个点,默认值(原点)可能也是“有效”值。
相反,您可以使用Nullable<ProportionPoint>
.
结构是值类型,与引用类型相反,它们永远不能为空。您可以检查默认值:
if (this.p.Equals(default(ProportionPoint)))
结构不能为null 。它是值类型,而不是引用类型。您需要检查具有默认值的属性。就像是:
if(p.X == 0 && p.Y == 0)
因为 p 是 struct 它永远不会为空,所以你应该将它与它的默认值进行比较。为了检查您的值和默认值之间的等价性。如果你使用 == 你会得到
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))
结构永远不能为空,因此您不能将其与空进行比较。并且结构总是被初始化 - 如果不是由你初始化,那么由编译器使用默认值。
使用可为空的:
ProportionPoint? p1 = null;
if (p1 == null) ...
或者
if (!p1.HasValue) ...
结构不能为空,但如果您确实想在任何时候在其中存储与默认值等效的值,则根据其默认值检查结构的解决方法可能会给出假阴性。
(例如,具有值的结构(0,0,0)
可以是未触及的默认值,或者它可以将原点存储在 3D 空间中。)
避免这种假阴性问题的另一种方法是向结构添加另一个属性 - 例如 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;
}
}
我做了一个只适用于结构的扩展方法:
public static bool IsNull<T>(this T source) where T:struct
{
return source.Equals(default(T));
}
调用约定:
if(myStruct.IsNull())
DoSomething();
我知道它并没有真正检查它是否是null
. 但是,如果我给它一个更准确的名称,比如IsEmpty
or IsDefault
,六个月后我会忘记它的存在,并且在看到可用方法列表时不会选择它。从技术上讲,这不是空检查;但从概念上讲它是。
与引用类型的变量或值不同,它是对该类型的零个或一个实例的引用,结构变量或值是结构实例。如果有一个以 开头的代码块{Point myPoint; ...}
,并且块中没有任何内容关闭MyPoint
(当yield return
块中有 a 时,或者当 lambda 或匿名方法使用封闭块中的变量时发生关闭),那么Point
will的实例在执行进入块之前的某个时间开始存在,并且可能在执行离开块后的任何时间停止存在。在任何可以使用结构类型变量的上下文中,结构都存在。
所有结构类型都被认为具有无操作默认构造函数的原因是结构类型隐含地存在。当执行类似 的语句时,它会创建一个由 100 个结构Point[] myPoints = new Point[100];
组成的零填充数组;Point
进行中,100
零填充点实例立即出现。在 C++ 中,如果一个类型具有构造函数,则创建该类型的数组将按顺序在数组的每个元素上调用构造函数,然后任何代码都可以访问该数组。如果在构造任何元素时抛出异常,编译器生成的代码将对在数组本身蒸发之前成功创建的每个元素运行确定性析构函数。虽然这是一个非常强大的功能,但将其包含在 .net 中会使框架大大复杂化。
您无法检查 struct 是否为 null,但您可以检查默认的未初始化值,如下所示:
if (instanceOfYourStruct == default)