2013-02-19 82 views
1

好吧,这是比实际需求更好奇。有没有一种方法可以防止结构被检测或我可以有一个类将被复制?

比方说,我有这个类:

public sealed class Entity 
{ 
    int value; 

    Entity() 
    { 

    } 

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

我不希望这个类给类以外的实例化,这工作做。但是这里的Entity将被引用,而不是像值类型那样被复制。这个类很小,我希望它表现得像值类型。另外,如果我比较Entity的两个实例,如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 

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

+0

你的意思是短重写“等于”方法或类上的“==”操作符来执行,只要你想的比较? – 2013-02-19 15:02:32

+0

@DavidW是的,这是可能的。但它仍然不会给类的价值类型语义,或换句话说我的要求1. – nawfal 2013-02-19 15:09:37

回答

2

它不可能在C#中重新定义或尝试隐藏结构的默认构造函数,因为C#编译器会基于假设无参数构造函数不做任何事情来常规地编译代码。见Why can't I define a default constructor for a struct in .NET?

你的选择是要么

  • 使用类
  • 确保您的结构中的默认值有一定的意义(例如,在你的情况整型将被初始化为0) - 这是枚举做(回想起枚举初始化为0)。

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

-1

使所有构造函数(除了静态构造函数)privateEntityprotected也可以工作,但由于其sealed,这并没有多大意义。

+0

你似乎没有得到我的问题。将构造函数设为私有使其不可实例化,但它是否符合我的要求1?没有.. – nawfal 2013-02-19 15:07:15

+0

你为什么不重写'Equals'? – 2013-02-19 15:11:46

+0

是的,这是可能的,但仍然是一个引用类型,而不是值类型,否则将被复制。我将编辑我的问题。 – nawfal 2013-02-19 15:12:50

1

一种类型没有发言可以发生该类型的存储位置。任何类型的存储位置都可以存在,或者其内容被相同类型的其他位置的内容覆盖,而类型本身没有任何发言权。引用类型的存储位置包含类引用;当它出现时,它将是一个空引用。引用类型的存储位置只能存储空引用以外的任何东西的唯一方法是,如果创建了该类型的实例,并且 - 涉及完全信任代码和反射的某些情况外 - 引用类型将完全控制可能发生的情况。

相比之下,值类型的存储位置是该类型的一个实例。因此,结构无法控制如何成立。什么样的结构可以控制 - 在一定程度上 - 它的领域可以包含哪些价值。在有限的信任方案中,如果结构的代码将该值写入结构的某个实例,则私有结构字段只能假定非默认值(如果该值被写入结构的任何实例,即使受限信任代码与访问该实例可能能够使用多线程重叠的读取和写入产生结构与组合,该结构本身绝不会自己创建的字段值)。

我建议创建一个类类型的单个私有字段一个struct。您无法阻止代码创建default(Entity),但这并不意味着您必须允许代码对其中的任何内容执行任何操作。它Equals方法应在与其他任何东西相比,工作不够好比较的另一个默认实例时返回truefalse,并GetHashCode应该为所有默认实例返回相同的值,但任何其他的方法可以抛出一个异常。

+0

如果我拥有班级类型的私人支持字段,它会给我带来什么好处?一个结构仍然是可实例化的。我会悲伤地用我最初的方法(贾斯汀的回答)。 – nawfal 2013-02-20 06:52:52

+0

@nawfal:在一个结构结束语一个类可以让你暴露从什么类本身会暴露不同的方法,并且还允许您控制默认情况下的行为。任何人都可以创建任何类型的变量 - 类或结构 - 并调用传递该变量的方法。在类类型的情况下,默认值变量会比较等于'null',并试图调用任何方法将抛出'NullReferenceException'。通过一个结构,你可以决定哪些效果方法应该对默认实例有效。 – supercat 2013-02-20 16:17:12

相关问题