60

我无法理解C# 语言中的 getter 和 setter 的概念。在像 Objective-C 这样的语言中,它们似乎是系统的一个组成部分,但在 C# 中却不是那么重要(据我所知)。我已经阅读过书籍和文章,所以我的问题是,对于那些了解 C# 中的 getter 和 setter 的人,如果你正在向一个完整的初学者教授这个概念,你个人会使用什么示例(这将包括几行代码尽可能)?

4

12 回答 12

82

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

public class Foo
{
   private string bar;

   public string GetBar()
   {
       return bar;
   }

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

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

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

public class Foo
{
    private string bar;

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

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

从 C# 3.0 及更高版本开始,编译器已优化到此类属性不需要将私有成员作为其源的程度。编译器自动生成该类型的私有成员并将其用作属性的来源。

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

代码显示的是一个自动属性,它具有由编译器生成的私有成员。您看不到私人成员,但它就在那里。这也引入了其他几个问题——主要是访问控制。在 C# 1.1 和 2.0 中,您可以省略属性的 get 或 set 部分:

public class Foo
{
    private string bar;

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

让您有机会限制其他对象如何与 Foo 类的“Bar”属性交互。从 C# 3.0 及更高版本开始 - 如果您选择使用自动属性,则必须指定对属性的访问权限,如下所示:

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

这意味着只有类本身可以将 Bar 设置为某个值,但是任何人都可以读取 Bar 中的值。

于 2012-06-22T15:49:46.733 回答
30

在 C# 中,Properties代表您的 Getter 和 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 specify 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
            if (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. 您不必同时指定 getter 和 setter,您可以省略其中任何一个。
  2. 属性只是传统 getter 和 setter 的“语法糖”。编译器实际上将在幕后(在编译的 IL 中)构建 get_ 和 set_ 函数,并将对您的属性的所有引用映射到这些函数。
于 2012-06-22T15:39:34.723 回答
14

大多数语言都是这样做的,你也可以在 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;
于 2012-06-22T15:40:40.917 回答
13

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


想象一个带有变量的类:

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,所以我们希望density在更改后立即重新计算weight

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

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() 等函数的频率。

于 2012-06-22T15:57:06.303 回答
6

C# 引入了可以为您完成大部分繁重工作的属性...

IE

public string Name { get; set; }

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

private string _name;

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

基本上,getter 和 setter 只是帮助封装的手段。当您创建一个类时,您有几个类变量,您可能希望将这些变量公开给其他类,以使它们能够瞥见您存储的一些数据。虽然一开始只公开变量似乎是一种可接受的选择,但从长远来看,您会后悔让其他类直接操作您的类成员变量。如果你通过一个 setter 强制他们这样做,你可以添加逻辑以确保不会出现奇怪的值,并且你可以在将来更改该逻辑,而不会影响已经在操纵这个类的东西。

IE

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; 
}
于 2012-06-22T15:44:15.030 回答
3

这里是实际用例中 getter setter 的常见用法,

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;}
}
于 2015-02-16T09:19:16.813 回答
1

这将是 C# 中使用尽可能少的代码的 get/set。您可以在 C# 3.0+ 中获得自动实现的属性

public class Contact
{
   public string Name { get; set; }
}
于 2012-06-22T15:41:20.857 回答
1

简单的例子

    public  class Simple
    {
        public int Propery { get; set; }
    }
于 2012-06-22T15:42:10.120 回答
1

据我了解,getter 和 setter 是为了改进封装。在 C# 中它们并不复杂。

您可以像这样定义 on 对象的属性:

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

您最终可以像这样对 setter 或 getter 中的值进行一些处理:

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

如果您跳过 set 或 get,您的属性将只能读取或写入。我就是这样理解这些东西的。

于 2012-06-22T15:44:07.387 回答
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.
}
于 2012-06-22T15:45:59.120 回答
0

C# 中的 Getter 和 Setter 可以简化代码。

private string name = "spots";

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

并调用它(假设我们有一个带有 name 属性的 person obj):

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!

于 2012-06-22T15:49:41.200 回答
0

这是一个带有 getter 和 setter 的对象“Article”的基本示例:

  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;
        }
    }
于 2015-03-17T18:45:19.040 回答