1

好的,这比实际要求更具好奇心。

假设我有这个课程:

public sealed class Entity
{
    int value;

    Entity()
    {

    }

    public static implicit operator Entity(int x)
    {
        return new Entity { value = x };
    }
}

我不希望这个类在类之外实例化,这很有效。但是这里Entity的 s 将被引用而不是像值类型一样被复制。这个类太小了,我希望它表现得像值类型。此外,如果我比较Entitys 的两个实例,就像e1 == e2它会给出引用相等(好的,我可以重载==,但这是更多的工作)。所以我会把它变成一个结构:

public struct Entity
{
    int value;

    public static implicit operator Entity(int x)
    {
        return new Entity { value = x };
    }
}

但现在有人可以new Entity()轻松做到。

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

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

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

4

3 回答 3

2

不可能重新定义或尝试隐藏 C# 中结构的默认构造函数,因为 C# 编译器通常会根据无参数构造函数不执行任何操作的假设来编译代码。请参阅为什么我不能为 .NET 中的结构定义默认构造函数?.

您的选择是

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

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

于 2013-02-19T15:14:40.020 回答
1

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

相比之下,值类型的存储位置是该类型一个实例。因此,一个结构无法控制一个结构是如何存在的。一个结构可以控制的——在有限的范围内——是它的字段可以包含什么值。在有限信任场景中,如果结构的代码将该值写入结构的某个实例(如果该值被写入结构的任何实例,甚至是有限信任代码,则私有结构字段只能假定非默认值)访问该实例可能能够使用多线程重叠读取和写入来生成一个结构,该结构具有该结构本身永远不会自行创建的字段值的组合)。

我建议创建一个具有类类型的单个私有字段的结构。你不能阻止代码创建一个default(Entity),但这并不意味着你必须允许代码对它做任何有用的事情。它的Equals方法应该足够好,以便true在与另一个默认实例比较时返回,以及false在与其他任何实例比较时,并且GetHashCode应该为所有默认实例返回相同的值,但任何其他方法都可能引发异常。

于 2013-02-19T16:03:57.070 回答
-1

private 创建所有构造函数(除了静态构造函数)Entityprotected也可以,但是因为它sealed,这没有多大意义。

于 2013-02-19T15:00:26.873 回答