2012-06-22 55 views
29

我无法理解C#语言中的getter和setter 的概念。在像Objective-C这样的语言中,它们似乎是系统中不可或缺的一部分,但在C#中并没有太多(,据我所知)。我已经阅读过书籍和文章,所以我的问题是,对于那些了解在C#中使用getter &设置器的人来说,如果你将这个概念教给一个完整的初学者,你会个人使用什么样的例子(这包括几行代码尽可能)?在C#中寻找一个简短和简单的getter/setter例子

+0

这是非常宽泛的。什么具体是给你C#属性的麻烦? – arcain

+0

这可能是一个重复的http://stackoverflow.com/questions/1209359/properties-and-methods – arcain

+0

我想知道在C#中的getters/setter与Objective C相比缺少什么? – Vlad

回答

13

在C#中,Properties代表你的Getters和Setter。

下面是一个例子:

public class PropertyExample 
{ 
    private int myIntField = 0; 

    public int MyInt 
    { 
     // This is your getter. 
     // it uses the accessibility of the property (public) 
     get 
     { 
      return myIntField; 
     } 
     // this is your setter 
     // Note: you can specifiy different accessibility 
     // for your getter and setter. 
     protected set 
     { 
      // You can put logic into your getters and setters 
      // since they actually map to functions behind the scenes 
      DoSomeValidation(value) 
      { 
       // The input of the setter is always called "value" 
       // and is of the same type as your property definition 
       myIntField = value; 
      } 
     } 
    } 
} 

你会访问该属性就像一个字段。例如:

PropertyExample example = new PropertyExample(); 
example.MyInt = 4; // sets myIntField to 4 
Console.WriteLine(example.MyInt); // prints 4 

其他一些注意事项: 1)你不必specifiy既是一个getter和一个setter,你可以省略任何一个。

2)属性只是“语法糖”为您的传统吸气和二传手。编译器实际上会在幕后编译get_和set_函数(在编译后的IL中),并将所有对您的属性的引用映射到这些函数。

11

大多数语言都是这样做的,你也可以在C#中完成它。

public void setRAM(int RAM) 
    { 
     this.RAM = RAM; 
    } 
    public int getRAM() 
    { 
     return this.RAM; 
    } 

但是C#还给出了更优雅的解决方案是:

public class Computer 
    { 
     int ram; 
     public int RAM 
     { 
      get 
      { 
        return ram; 
      } 
      set 
      { 
        ram = value; // value is a reserved word and it is a variable that holds the input that is given to ram (like in the example below) 
      } 
     } 
    } 

,后来与访问它。

Computer comp = new Computer(); 
    comp.RAM = 1024; 
    int var = comp.RAM; 

对于C#的新版本,它甚至更好:

public class Computer 
{ 
    public int RAM { get; set; } 
} 

及更高版本:

Computer comp = new Computer(); 
comp.RAM = 1024; 
int var = comp.RAM; 
+0

感谢您解释“价值”实际上是什么 – jskidd3

1

简单的例子

public class Simple 
    { 
     public int Propery { get; set; } 
    } 
1

据我了解getter和setter方法是改善封装。 C#中没有什么复杂的。

您对对象定义的属性是这样的:

int m_colorValue = 0; 
public int Color 
{ 
    set { m_colorValue = value; } 
    get { return m_colorValue; } 
} 

这是最简单的使用。它基本上设置一个内部变量或检索其值。 您可以使用一个属性是这样的:

someObject.Color = 222; // sets a color 222 
int color = someObject.Color // gets the color of the object 

你可能最终做这样的制定者或干将值一些处理:

public int Color 
{ 
    set { m_colorValue = value + 5; } 
    get { return m_colorValue - 30; } 
} 

如果你跳过设置或获取,你的财产将被只读或写。这就是我对这些东西的理解。

3

C#引入了做最繁重的任务,你的属性...

public string Name { get; set; } 

是C#快捷方式编写...

private string _name; 

public string getName { return _name; } 
public void setName(string value) { _name = value; } 

基本上getter和制定者只是帮助封装的手段。当你创建一个类的时候,你有几个类变量,可能你想暴露给其他类,让他们能够看到你存储的一些数据。虽然只是将变量公开给变量看起来可以接受,但从长远来看,您会后悔让其他类直接操作您的类成员变量。如果你强迫他们通过setter来完成,你可以添加逻辑来确保不会出现任何奇怪的值,并且你可以随时改变这个逻辑,而不会影响已经操作这个类的东西。

private string _name; 

public string getName { return _name; } 
public void setName(string value) 
{ 
    //Don't want things setting my Name to null 
    if (value == null) 
    { 
     throw new InvalidInputException(); 
    } 
    _name = value; 
} 
+0

沉默忽略了在输入错误的情况下设置通常是一个糟糕的主意 – Vlad

+0

对于一个简单的例子可能没问题,但我编辑的时候是一个异常而不是无声的忽略。 –

0

内部,getter和setter方法都只是方法。另外,在C#编译,它生成的getter和setter这样的方法,例如:

public int get_MyProperty() { ... } 
public void set_MyProperty(int value) { ... } 

C#允许您使用短手语法来声明这些方法。在构建应用程序时,下面的代码将被编译到上面的方法中。

public int MyProperty { get; set; } 

private int myProperty; 
public int MyProperty 
{ 
    get { return myProperty; } 
    set { myProperty = value; } // value is an implicit parameter containing the value being assigned to the property. 
} 
0

getter和setter在C#中的东西,简化了代码。

private string name = "spots"; 

public string Name 
{ 
    get { return name; } 
    set { name = value; } 
} 

,把它(假设我们有一个人的obj与name属性):

Console.WriteLine(Person.Name); //prints "spots" 
Person.Name = "stops"; 
Console.Writeline(Person.Name); //prints "stops" 

这简化了你的代码。在Java中,你可能必须有两个方法,一个用于Get(),另一个用于Set()该属性,在C#中它全部在一个地方完成。我通常做这在我的课的开始:

public string foobar {get; set;} 

这为我的foobar的属性getter和setter。调用它与之前所示的方式相同。值得注意的是,你不必同时包含get和set。如果你不想修改该属性,请不要包含set!

41

我认为一些代码将有助于说明什么getter和setter方法是:

public class Foo 
{ 
    private string bar; 

    public string GetBar() 
    { 
     return bar; 
    } 

    public void SetBar(string value) 
    { 
     bar = value; 
    } 
} 

在这个例子中,我们有一个名为bar类的私有成员。 GetBar和SetBar方法完全按照它们的名称命名 - 一个检索条形成员,另一个设置其值。

在c#1.1 +你有属性。基本功能也是一样的:

public class Foo 
{ 
    private string bar; 

    public string Bar 
    { 
     get { return bar; } 
     set { bar = value; } 
    } 
} 

私人成员栏不能在课堂外访问。然而,公共“Bar”是,并且它有两个访问器 - 就像上面“GetBar()”的例子返回私有成员一样,也是一个set - 它对应于前面提到的SetBar(string value)方法例。

从C#3.0及以上版本开始,编译器进行了优化,使得这些属性不需要私有成员作为源。编译器自动生成该类型的私有成员,并将其用作属性的来源。

public class Foo 
{ 
    public string Bar { get; set; } 
} 

代码显示的是具有由编译器生成的私有成员的自动属性。你没有看到私人成员,但它在那里。这也引入了其他一些问题 - 主要是访问控制。在C#1.1和2.0,你可以省略属性获取或设置部分:

public class Foo 
{ 
    private string bar; 

    public string Bar 
    { 
     get{ return bar; } 
    } 
} 

给你限制对象是如何与其他Foo类的“栏”属性交流的机会。用C#3.0及以上开始 - 如果你选择使用自动属性,你就必须指定属性的访问如下:

public class Foo 
{ 
    public string Bar { get; private set; } 
} 

这是什么意思是,只有类本身可以设置酒吧为某个值,然而任何人都可以阅读Bar中的值。

3

我的解释如下。 (这不是那么短,但它是非常简单的。)


试想一类的变量:

class Something 
{ 
    int weight; 
    // and other methods, of course, not shown here 
} 

嗯,有一个小问题,这个类:没有人能看到weight 。我们可以公开制作weight,但随后每个人都可以随时更改weight(这可能不是我们想要的)。所以,好了,我们可以做一个函数:

class Something 
{ 
    int weight; 
    public int GetWeight() { return weight; } 
    // and other methods 
} 

这已经是最好的,但现在大家的不是纯something.Weight具有输入something.GetWeight(),这是很好的,丑陋的。

其属性,我们可以这样做,但代码保持清洁:

class Something 
{ 
    public int weight { get; private set; } 
    // and other methods 
} 

int w = something.weight // works! 
something.weight = x; // doesn't even compile 

尼斯,因此与性质,我们有超过变量的访问更精细的控制。

另一个问题:没关系,我们希望外部代码能够设置weight,但我们希望能控制它的价值,而不是允许比100更低的权重。此外,还有一些其他的内部变量density ,这取决于weight,所以我们希望在weight更改后立即重新计算density

这是通过以下方式传统上实现:

class Something 
{ 
    int weight; 
    public int SetWeight(int w) 
    { 
     if (w > 100) 
      throw new ArgumentException("weight too small"); 
     weight = w; 
     RecalculateDensity(); 
    } 
    // and other methods 
} 

something.SetWeight(anotherSomething.GetWeight() + 1); 

但同样,我们不希望暴露给我们的客户,设置的权重是一个复杂的操作,它的语义只是分配一个新的权重。所以带有setter的代码看起来是一样的,但更好:

class Something 
{ 
    private int _w; 
    public int Weight 
    { 
     get { return _w; } 
     set 
     { 
      if (value > 100) 
       throw new ArgumentException("weight too small"); 
      _w = value; 
      RecalculateDensity(); 
     } 
    } 
    // and other methods 
} 

something.Weight = otherSomething.Weight + 1; // much cleaner, right? 

所以,毫无疑问,属性是“只是”一个语法糖。但它使客户的代码变得更好。有趣的是,需要类似财产的东西经常出现,您可以检查其他语言中GetXXX()和SetXXX()函数的频率。

+0

这是我学习风格的绝佳例子 – CM90

+1

@ CM90:谢谢! :) – Vlad

+0

真的很好解释:) –

1

那么这里是在实际使用情况下的吸气剂的共同使用,

public class OrderItem 
{ 
public int Id {get;set;} 
public int quantity {get;set;} 
public int Price {get;set;} 
public int TotalAmount {get {return this.quantity *this.Price};set;} 
} 
0

这是一个对象“条”与getter和setter的一个基本的例子:

public class Article 
    { 

     public String title; 
     public String link; 
     public String description; 

     public string getTitle() 
     { 
      return title; 
     } 

     public void setTitle(string value) 
     { 
      title = value; 
     } 

     public string getLink() 
     { 
      return link; 
     } 

     public void setLink(string value) 
     { 
      link = value; 
     } 
     public string getDescription() 
     { 
      return description; 
     } 

     public void setDescription(string value) 
     { 
      description = value; 
     } 
    } 
+0

这里较好的东西是变量本身公开,这是一个糟糕的面向对象范例。特别是当你在它旁边有明确的制定者和获得者时。更好的是部署C#范例:public String Title {get;组}; (对于其他2个变量也是如此)。这包含了外部世界中的(不可见的,但是生成的)私有变量。 – GeertVc