在C#中寻找一个简短的getter/setter示例

CM9*_*M90 53 c# getter setter getter-setter

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

ble*_*ter 64

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

public class Foo
{
   private string bar;

   public string GetBar()
   {
       return bar;
   }

   public void SetBar(string value)
   {
       bar = value;
   }
}
Run Code Online (Sandbox Code Playgroud)

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

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

public class Foo
{
    private string bar;

    public string Bar
    {
        get { return bar; }
        set { bar = value; }
    }
}
Run Code Online (Sandbox Code Playgroud)

私人会员酒吧在课外无法访问.然而大众"酒吧"是,它有两个访问 - 获得,这正如上述"GetBar()"的示例返回私有成员,也是一组 - 这相当于SetBar(字符串值)方法在forementioned例.

从C#3.0及更高版本开始,编译器已经过优化,以至于此类属性不需要将私有成员作为其源.编译器自动生成该类型的私有成员,并将其用作属性的源.

public class Foo
{
   public string Bar { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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

public class Foo
{
    private string bar;

    public string Bar
    {
        get{ return bar; }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

public class Foo
{
    public string Bar { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

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


Jon*_*yna 25

在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 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
            DoSomeValidation(value)
            {
                // The input of the setter is always called "value"
                // and is of the same type as your property definition
                myIntField = value;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以像字段一样访问此属性.例如:

PropertyExample example = new PropertyExample();
example.MyInt = 4; // sets myIntField to 4
Console.WriteLine( example.MyInt ); // prints 4
Run Code Online (Sandbox Code Playgroud)

其他一些注意事项:

  1. 您不必同时指定getter和setter,您可以省略其中任何一个.
  2. 属性只是传统getter和setter的"语法糖".编译器实际上将在幕后(在编译的IL中)构建get_和set_函数,并将对属性的所有引用映射到这些函数.


Iks*_*eto 14

大多数语言都是这样做的,你也可以用C#来实现.

    public void setRAM(int RAM)
    {
        this.RAM = RAM;
    }
    public int getRAM()
    {
        return this.RAM;
    }
Run Code Online (Sandbox Code Playgroud)

但是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 )
             }
        }
     }
Run Code Online (Sandbox Code Playgroud)

然后再访问它.

    Computer comp = new Computer();
    comp.RAM = 1024;
    int var = comp.RAM;
Run Code Online (Sandbox Code Playgroud)

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

public class Computer
{
    public int RAM { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后 :

Computer comp = new Computer();
comp.RAM = 1024;
int var = comp.RAM;
Run Code Online (Sandbox Code Playgroud)

  • 感谢您解释实际上是什么"价值" (2认同)

Vla*_*lad 11

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


想象一个带变量的类:

class Something
{
    int weight;
    // and other methods, of course, not shown here
}
Run Code Online (Sandbox Code Playgroud)

嗯,这个类有一个小问题:没有人能看到weight.我们可以weight公开,但随后每个人都可以随时改变weight(这可能不是我们想要的).那么,我们可以做一个功能:

class Something
{
    int weight;
    public int GetWeight() { return weight; }
    // and other methods
}
Run Code Online (Sandbox Code Playgroud)

这已经更好了,但现在每个人都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
Run Code Online (Sandbox Code Playgroud)

很好,所以有了属性,我们可以更好地控制变量访问.

另外一个问题:没关系,我们希望外部代码能够设置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);
Run Code Online (Sandbox Code Playgroud)

但同样,我们不希望向我们的客户透露设置权重是一项复杂的操作,它在语义上只是分配一个新的权重.所以带有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?
Run Code Online (Sandbox Code Playgroud)

所以,毫无疑问,属性"只是"一种语法糖.但它使客户的代码更好.有趣的是,对类似属性的事物的需求经常出现,您可以检查在其他语言中找到GetXXX()和SetXXX()等函数的频率.


Kev*_*lia 6

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

IE

public string Name { get; set; }
Run Code Online (Sandbox Code Playgroud)

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

private string _name;

public string getName { return _name; }
public void setName(string value) { _name = value; }
Run Code Online (Sandbox Code Playgroud)

基本上 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; 
}
Run Code Online (Sandbox Code Playgroud)