C#中的属性解析(get、set、value)
目录
- C#中的属性(get、set、value)
- C#中属性的定义
C#中的属性(get、set、value)
C#语言在面向对象设计和编程中对数据安全提出了严格的要求,其中一个重要的原则就是数据封装。根据这一原则,C#程序设计中要求开发人员对特定类的数据字段尽量不以公有方式提供给外界。因此在类内部多数字段的访问权限被限定为private或是public,而这些字段与外界的交流经常采用属性来进行。
属性使类能够以一种公开的方法获取和设置值,同时隐藏实现或验证代码。
属性是这样的成员:它们提供灵活的机制来读取、编写或计算私有字段的值。
可以像使用公共数据成员一样使用属性,但实际上它们是称作“访问器”的特殊方法。这 使得可以轻松访问数据,此外还有助于提高方法的安全性和灵活性。
属性使类能够以一种公开的方法获取和设置值,同时隐藏实现或验证代码。
get 属性访问器用于返回属性值,而 set 访问器用于分配新值。 这些访问器可以有不同的访问级别。
get 访问器体与方法体相似。 它必须返回属性类型的值。执行 get 访问器相当于读取字段的值
get 访问器必须以 return 或 throw 语句终止,并且控制权不能离开访问器体。
value 关键字用于定义由 set 取值函数分配的值。
不实现 set 取值函数的属性是只读的。
属性的定义通常由以下两部分组成:
1、需要封装的专用数据成员
private int _nValue = 1; private double _dValue = 10.101; private char _chValue = 'a';
2、向外界提供访问的公共属性:
//读写属性nValue: public int nValue { get { return _nValue; } set { _nValue = value; } } //只读属性dValue: public double dValue { get { return _dValue; } } //只写属性chValue: public char chValue { set { _chValue = value; } }
当属性的访问器中不需要其他逻辑时,自动实现的属性可使属性声明更加简洁。客户端还可以通过这些属性创建对象,例如下面的代码,编译器将创建一个私有的匿名支持字段,该字段只能通过属性的get和set访问器进行访问。
class Customer { // Auto-Impl Properties for trivial get and set public double TotalPurchases { get; set; } public string Name { get; set; } public int CustomerID { get; set; } // Constructor public Customer(double purchases, string name, int ID) { TotalPurchases = purchases; Name = name; CustomerID = ID; } // Methods public string GetContactInfo() {return "ContactInfo";} public string GetTransactionHistory() {return "History";} // .. Additional methods, events, etc. } class Program { static void Main() { // Intialize a new object. Customer cust1 = new Customer ( 4987.63, "Northwind",90108 ); //Modify a property cust1.TotalPurchases += 499.99; } }
下面讲一个如何使用自动实现的属性实现轻量类:
此示例演示如何创建一个不可变轻量类,用于仅封装一组自动实现的属性。当您必须使用引用类型语义时,请使用此种构造而不是结构。
请注意:对于自动实现的属性,需要 get 和 set 访问器。 要使该类不可变,请将 set 访问器声明为 private。 但是,声明私有 set 访问器时,不能使用对象初始值来初始化属性。
下面的示例演示两种方法来实现具有自动实现属性的不可变类。第一个类使用构造函数初始化属性,第二个类使用静态工厂方法。
class Contact { // Read-only properties. public string Name { get; private set; } public string Address { get; private set; } // Public constructor. public Contact(string contactName, string contactAddress) { Name = contactName; Address = contactAddress; } } // This class is immutable. After an object is created, // it cannot be modified from outside the class. It uses a // static method and private constructor to initialize its properties. public class Contact2 { // Read-only properties. public string Name { get; private set; } public string Address { get; private set; } // Private constructor. private Contact2(string contactName, string contactAddress) { Name = contactName; Address = contactAddress; } // Public factory method. public static Contact2 CreateContact(string name, string address) { return new Contact2(name, address); } } public class Program { static void Main() { // Some simple data sources. string[] names = {"Terry Adams","Fadi Fakhouri", "Hanying Feng", "Cesar Garcia", "Debra Garcia"}; string[] addresses = {"123 Main St.", "345 Cypress Ave.", "678 1st Ave", "12 108th St.", "89 E. 42nd St."}; // Simple query to demonstrate object creation in select clause. // Create Contact objects by using a constructor. var query1 = from i in Enumerable.Range(0, 5) select new Contact(names[i], addresses[i]); // List elements cannot be modified by client code. var list = query1.ToList(); foreach (var contact in list) { Console.WriteLine("{0}, {1}", contact.Name, contact.Address); } // Create Contact2 objects by using a static factory method. var query2 = from i in Enumerable.Range(0, 5) select Contact2.CreateContact(names[i], addresses[i]); // Console output is identical to query1. var list2 = query2.ToList(); // List elements cannot be modified by client code. // CS0272: // list2[0].Name = "Eugene Zabokritski"; // Keep the console open in debug mode. Console.WriteLine("Press any key to exit."); Console.ReadKey(); } } /* Output: Terry Adams, 123 Main St. Fadi Fakhouri, 345 Cypress Ave. Hanying Feng, 678 1st Ave Cesar Garcia, 12 108th St. Debra Garcia, 89 E. 42nd St. */
上诉中,通过get存取器和set存取器将封装好的专有数据成员和共同属性关联起来。
此时,value关键字是时候出场了。
在普通的C#程序中,一般不能通过常用的调试手段获得value值传递的详细过程,不能像C++中一样跟踪指针的变化情况。当使用如下语句给属性赋值:
Class ValueCollector{...}; ValueCollector newValue = new ValueCollector(); newValue.nValue = 10;
新对象newValue的私有数据成员_nValue通过属性nValue的set方法由原来的1改变为10;
赋值语句的右值通过隐式参数value进入属性set方法内,成功改变整型私有变量的值。
在这一过程中,value参数的类型是整型,与属性的类型是一致的。当属性的类型改变为char,value参数的属性也相应的改变为字符型。
这种参数类型的自动转换时基于.NETFramework提供的类型转换器而实现的,CLR将C#源代码编译成中间语言IL,在这种类汇编的高级机器语言中可以发现value参数的传递机制。
C#中属性的定义
属性的定义
定义结构:
public int MyIntProp{ get{ //get code } set{ //set code } }
- 定义属性需要名字和类型。
- 属性包含两个块:get块和set块。
- 访问属性和访问字段一样,当取得属性的值得时候,就会调用属性中的get块,因此get块需要返回值,其返回值类型就是属性的类型;当我们去给属性设置值得时候,就会调用属性中的set块,以此可以在set块中通过value访问到我们所设置的值。
eg:
//跟访问字段的方式一样 v1.MyIntProperty = 600; //对属性设置值,自动调用set块 int temp = v1.MyIntProperty //对属性取值,自动调用get块
需要注意的是,set方法和get方法可以不同时存在。
但是如果没有get块,就不可以获得取值;如果没有set块,就不能进行设置值。
通过属性访问字段
一般而言,习惯于将字段设置为private,这样外界就不能修改字段的值。这是我们可以通过定义属性来设置字段和获取字段的值。
eg:
private int age; public int Age{ //习惯字段小写,属性大写 set{ if(value<0) return; //通过set值进行一些校验的工作 age = value; } get{ return age; } }
设置属性的只读或者只写
只读
private string name; public string Name{ get{ return name; }
只写
private string name; public string Name{ set{ name = value; }
属性的访问修饰符
//如果在get或set块钱加上private,表示这个块只能在类内进行调用 public float X{ private set { x = value;} get { return x;} public float X{ set { x = value;} private get { return x;}
自动实现的属性
public int Age{set;get;} //编译器会自动提供字段来存储age -->等价于 public int Age{ set{ age = value;} get{ return age;}
总结一下,属性就相当于是一种带有set和get方法的一个方法,而它与类中的字段的赋值和取值又是息息相关的。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。