2013-01-09 97 views
2

,应注意以下...设置变量定义VS

//pattern 1 
public class Cheesesteak 
{ 
    public string bread {get; private set} 
    public string cheese {get; private set} 

    public Cheesesteak() 
    { 
     bread = "Amoroso"; 
     cheese = "Cheez Whiz"; 
    } 
} 

//pattern 2 
public class Cheesesteak 
{ 
    public string bread 
    { 
     get {return bread;} 
     set 
     { 
      bread = "Amoroso"; 
     } 
    } 
    public string cheese 
    { 
     get {return cheese;} 
     set 
     { 
      cheese = "Cheez Whiz"; 
     } 
    } 
    public Cheesesteak() {} 
} 

这是一个好奇的问题。是否有任何优势或特殊原因,你会设置变量在“集”的定义与在构造函数中声明它们?我最初的猜测是模式1较短,但在编译期间效率较低。

+5

模式2是一个堆栈溢出。 – SLaks

+0

@SLaks ..给予这个网站的名称似乎是适当的? :P –

+0

标记为以下副本:http://stackoverflow.com/questions/24551/best-practice-initialize-class-fields-in-constructor-or-at-declaration请阅读那里的评论/答案。 – lahsrah

回答

8

是否有任何优势或特殊原因,你会设置变量在“集”的定义与在构造函数中声明它们?

不,事实上,这可能不是你想要的。因为任何呼叫(例如bread = "rye";)都会将其设置为“Amoroso”(如果它有效,但会导致StackOverflowException),将无法设置“break”或“cheese”。另请注意,尝试检索代码中的值将导致StackOverflowException,属性获取器返回属性而不是后备字段值。

你是这可能心想:

public class Cheesesteak 
{ 
    private string bread = "Amoroso"; 
    public string Bread 
    { 
     get {return bread;} 
     set 
     { 
      bread = value; 
     } 
    } 

    // ... 

这里唯一的好处是你设置在字段定义的“默认”值,可以在某些情况下维护或可读性帮忙,甚至可能消除对定义的构造函数的需求,这可能会减少代码的总长度。

我最初的猜测是模式1较短,但在编译期间效率较低。

通常,将字段设置为内联值或将它们设置在构造函数中并不会降低效率。编译器会使类型的实际构造函数先设置字段,然后运行构造函数代码,这样两个版本在编译后的IL方面最终(实际用途)是一样的。这不是效率问题,而是代码可读性和可维护性。

需要注意的是,如果你想要的属性始终是一个常数(即:Bread应该始终回报"Amoroso"),你可以让拥有房产的一个getter和没有setter:

public string Bread { get { return "Amoroso"; } } 

我怀疑情况并非如此,但我想我会提及它作为一种选择,以防万一它是你的意图。

+1

@ReedCopsey事实上,两者都会导致国有企业。吸气和吸气者都会无限地递归自己。 – cdhowie

+2

呃,你们两个正在争论破碎的代码。 –

+0

@NominSim我改写为明确的 –

1

那么第二个选项将导致StackOverflowException每当用户试图分配访问属性,而第一个只允许私人访问它们。

你也许意思大概是:

private string bread = "Amaroso"; 
public string Bread 
{ 
    get { return bread; } 
    private set 
    { 
     bread = value; 
    } 
} 

这将初始化属性与“Amaroso”,但不会允许它被公开设置。

+0

而且当用户尝试检索属性值时。两个访问器都是SOE陷阱等待爆炸。 – cdhowie

+0

@cdhowie谢谢,编辑反映。 – NominSim

0

不,它们完全不同。 getset块实际上是在读取或写入属性时执行的方法。他们的虚空有什么做初始化。

var x = thing.Property; // Property's "get" accessor method is executed 
thing.Property = x; // Property's "set" accessor method is executed 

在你的第二个例子中,两个属性访问器都会无限递归自己,你将得到一个StackOverflowException。