C# 有没有一种方法可以防止struct被精神错乱,或者可以复制一个类?

C# 有没有一种方法可以防止struct被精神错乱,或者可以复制一个类?,c#,reference,struct,value-type,default-constructor,C#,Reference,Struct,Value Type,Default Constructor,好吧,这是好奇心多于实际需求 假设我有一门课: public sealed class Entity { int value; Entity() { } public static implicit operator Entity(int x) { return new Entity { value = x }; } } 我不希望这个类在类之外被实例化,这是可行的。但是这里将引用实体s,而不是像值类型那样复制。这个类

好吧,这是好奇心多于实际需求

假设我有一门课:

public sealed class Entity
{
    int value;

    Entity()
    {

    }

    public static implicit operator Entity(int x)
    {
        return new Entity { value = x };
    }
}
我不希望这个类在类之外被实例化,这是可行的。但是这里将引用
实体
s,而不是像值类型那样复制。这个类非常小,我希望它的行为类似于值类型。另外,如果我比较
实体
的两个实例,比如
e1==e2
,它将给出引用等式(好的,我可以重载
=
,但这需要更多的工作)。所以我会把它做成一个结构:

public struct Entity
{
    int value;

    public static implicit operator Entity(int x)
    {
        return new Entity { value = x };
    }
}
但是现在有人可以轻松地创建
newentity()

我的问题是,有没有一种方法可以让类型(结构/类)

1) 将在每次访问该值时复制,以便

Entity e1 = 1;
Entity e2 = e1;
ReferenceEquals(e1, e2); // prints false, just like any value type
2) 比较是否相等时具有值语义

Entity e1 = 1;
Entity e2 = 1;
e1.Equals(e2); // prints true

// this is easy though by overriding default equality.
3) 在类型的范围之外不可实例化:

Entity e = new Entity(); // should not compile

基本上接近枚举的行为。没有它我当然可以生活,只是学习

使类
实体的所有构造函数(静态构造函数除外)
私有
<代码>受保护的
也会起作用,但由于它的
是密封的
,这没有多大意义。

不可能在C中重新定义或试图隐藏结构的默认构造函数,因为C编译器通常基于无参数构造函数不做任何事情的假设来完成代码。看

你的选择是

  • 使用一个类
  • 确保结构的默认值具有某种意义(例如,在您的情况下,int将被初始化为0)-这是枚举所做的(回想一下,枚举被初始化为0)

我的建议是使用一个类,直到您发现存在性能问题。

类型对该类型的存储位置可能发生的情况没有发言权。任何类型的存储位置都可以存在,或者它们的内容被同一类型的其他位置的内容覆盖,而该类型本身对此没有任何发言权。引用类型的存储位置保存类引用;当它出现时,它将是一个空引用。引用类型的存储位置保存空引用以外的任何内容的唯一方法是创建该类型的实例,并且在某些涉及完全信任代码和反射的场景之外,引用类型将完全控制可能发生这种情况的环境

相反,值类型的存储位置是该类型的实例。因此,一个结构无法控制一个人是如何存在的。结构可以控制的——在有限的范围内——是其字段可以包含的值。在有限信任场景中,只有当结构的代码将非默认值写入结构的某个实例时,私有结构字段才能采用该值(如果将该值写入结构的任何实例,则即使访问该实例的有限信任代码也可以使用多线程重叠读写来生成具有字段值组合的结构,而这些字段值是结构本身永远不会创建的)


我建议使用类类型的单个私有字段创建一个结构。您不能阻止代码创建
默认值(实体)
,但这并不意味着您必须允许代码对一个实例执行任何有用的操作。它的
Equals
方法在与另一个默认实例进行比较时应该能够很好地返回
true
,在与其他实例进行比较时返回
false
,并且
GetHashCode
应该为所有默认指令返回相同的值但是任何其他方法都可能引发异常。

您的意思是没有覆盖“Equals”方法还是“==”类上的运算符来执行您想要的比较?@DavidW是的,这是可能的。但它仍然不会给出类的值类型语义,或者换句话说,我的要求1。您似乎没有理解我的问题。将构造函数私有化使其不可实例化,但它是否满足我的要求1?不……您为什么不重写
 等于
?是的,这是可能的,但它仍然是引用类型,而不是值类型,否则将被复制。我将编辑我的问题。如果我有类类型的私有支持字段,它会给我带来什么好处?结构仍然是可实例化的。我将使用我最初的方法(Justin的答案)遗憾的是,@nawfal:将类包装到结构中可以使您公开不同于类本身所公开的方法,还可以控制默认实例的行为。任何人都可以创建任何类型的变量——类或结构——并调用传递该变量的方法。对于类类型,默认值变量是将比较等于
null
,尝试调用任何方法将抛出
NullReferenceException
。通过结构,您可以决定方法对默认实例的影响。