我无法理解C# 语言中的 getter 和 setter 的概念。在像 Objective-C 这样的语言中,它们似乎是系统的一个组成部分,但在 C# 中却不是那么重要(据我所知)。我已经阅读过书籍和文章,所以我的问题是,对于那些了解 C# 中的 getter 和 setter 的人,如果你正在向一个完整的初学者教授这个概念,你个人会使用什么示例(这将包括几行代码尽可能)?
12 回答
我认为一些代码将有助于说明什么是 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 中的值。
在 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
其他一些需要注意的事项:
- 您不必同时指定 getter 和 setter,您可以省略其中任何一个。
- 属性只是传统 getter 和 setter 的“语法糖”。编译器实际上将在幕后(在编译的 IL 中)构建 get_ 和 set_ 函数,并将对您的属性的所有引用映射到这些函数。
大多数语言都是这样做的,你也可以在 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;
我的解释如下。(它不是那么短,但它很简单。)
想象一个带有变量的类:
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() 等函数的频率。
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;
}
这里是实际用例中 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;}
}
这将是 C# 中使用尽可能少的代码的 get/set。您可以在 C# 3.0+ 中获得自动实现的属性。
public class Contact
{
public string Name { get; set; }
}
简单的例子
public class Simple
{
public int Propery { get; set; }
}
据我了解,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,您的属性将只能读取或写入。我就是这样理解这些东西的。
在内部,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.
}
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!
这是一个带有 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;
}
}