C# 字段和属性之间有什么区别?
在C#中,是什么使字段不同于属性,以及何时应该使用字段而不是属性?属性公开字段。字段应该(几乎总是)对类保持私有,并通过get和set属性进行访问。属性提供了一个抽象级别,允许您更改字段,同时不影响使用类的对象访问字段的外部方式C# 字段和属性之间有什么区别?,c#,oop,properties,field,C#,Oop,Properties,Field,在C#中,是什么使字段不同于属性,以及何时应该使用字段而不是属性?属性公开字段。字段应该(几乎总是)对类保持私有,并通过get和set属性进行访问。属性提供了一个抽象级别,允许您更改字段,同时不影响使用类的对象访问字段的外部方式 public class MyClass { // this is a field. It is private to your class and stores the actual data. private string _myField;
public class MyClass
{
// this is a field. It is private to your class and stores the actual data.
private string _myField;
// this is a property. When accessed it uses the underlying field,
// but only exposes the contract, which will not be affected by the underlying field
public string MyProperty
{
get
{
return _myField;
}
set
{
_myField = value;
}
}
// This is an AutoProperty (C# 3.0 and higher) - which is a shorthand syntax
// used to generate a private field for you
public int AnotherProperty { get; set; }
}
@Kent指出,封装字段不需要属性,它们可以对其他字段进行计算,或者用于其他目的
@GSS指出,您还可以在访问属性时执行其他逻辑,例如验证,这是另一个有用的功能。属性公开字段。字段应该(几乎总是)对类保持私有,并通过get和set属性进行访问。属性提供了一个抽象级别,允许您更改字段,同时不影响使用类的对象访问字段的外部方式
public class MyClass
{
// this is a field. It is private to your class and stores the actual data.
private string _myField;
// this is a property. When accessed it uses the underlying field,
// but only exposes the contract, which will not be affected by the underlying field
public string MyProperty
{
get
{
return _myField;
}
set
{
_myField = value;
}
}
// This is an AutoProperty (C# 3.0 and higher) - which is a shorthand syntax
// used to generate a private field for you
public int AnotherProperty { get; set; }
}
@Kent指出,封装字段不需要属性,它们可以对其他字段进行计算,或者用于其他目的
@GSS指出,当访问属性时,您还可以执行其他逻辑,例如验证,这是另一个有用的功能。面向对象的编程原则说,类的内部工作应该对外部世界隐藏。如果您公开一个字段,那么本质上就是公开类的内部实现。因此,我们用属性(或者Java的方法)包装字段,使我们能够在不破坏代码的情况下更改实现。因为我们可以在属性中放置逻辑,所以如果需要,也可以执行验证逻辑等。 C#3可能有一个令人困惑的自动属性概念。这允许我们简单地定义属性,C#3编译器将为我们生成私有字段
public class Person
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public int Age{get;set;} //AutoProperty generates private field for us
}
面向对象的编程原则认为,类的内部工作应该对外部世界隐藏。如果您公开一个字段,那么本质上就是公开类的内部实现。因此,我们用属性(或者Java的方法)包装字段,使我们能够在不破坏代码的情况下更改实现。因为我们可以在属性中放置逻辑,所以如果需要,也可以执行验证逻辑等。 C#3可能有一个令人困惑的自动属性概念。这允许我们简单地定义属性,C#3编译器将为我们生成私有字段
public class Person
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public int Age{get;set;} //AutoProperty generates private field for us
}
如果要使用线程原语,则必须使用字段。属性可以破坏线程代码。除此之外,cory所说的是正确的。如果要使用线程原语,则必须使用字段。属性可以破坏线程代码。除此之外,cory所说的是正确的。属性封装字段,从而使您能够对要设置或检索的值执行附加处理。如果不对字段值进行任何预处理或后处理,则使用属性通常是过分的。属性封装字段,从而使您能够对要设置或检索的值执行附加处理。如果不对字段值进行任何预处理或后处理,则使用属性通常是过分的。属性的主要优点是允许您在不破坏对象的公共接口的情况下更改对象上的数据访问方式。例如,如果需要添加额外的验证,或将存储字段更改为计算字段,则如果最初将字段作为属性公开,则可以轻松地执行此操作。如果您只是直接公开了一个字段,那么您必须更改类的公共接口以添加新功能。这一更改将破坏现有客户机,要求它们在使用新版本的代码之前重新编译
如果您编写的类库是为广泛使用而设计的(比如.NET Framework,它被数百万人使用),那么这可能是一个问题。但是,如果您正在编写一个在小型代码库内部使用的类(假设属性的主要优点是允许您在不破坏对象的公共接口的情况下更改对象上的数据访问方式。例如,如果您需要添加额外的验证,或将存储字段更改为计算字段,则如果您最初将字段作为属性公开,则可以轻松地执行此操作。如果您只公开了字段,则实际上,您必须更改类的公共接口以添加新功能。该更改将破坏现有客户端,要求它们在使用新版本的代码之前重新编译
如果您编写一个为广泛使用而设计的类库(如供数百万人使用的.NET Framework),这可能是一个问题。但是,如果您编写一个在小型代码库内部使用的类(例如),属性允许您在设置值时使用逻辑 因此,您可以说您只想将值设置为整数字段,如果该值大于x,则抛出异常
非常有用的功能。此外,属性允许您在设置值时使用逻辑 因此,您可以说您只想将值设置为整数字段,如果该值大于x,则抛出异常
非常有用的功能。在后台,属性被编译成方法。因此,
名称
属性被编译成get\u Name()
和set\u Name(字符串值)
。如果您研究编译后的代码,可以看到这一点。
因此,使用它们时会产生(非常)小的性能开销。通常,如果将字段公开给外部,您将始终使用属性,如果需要验证值,您通常会在内部使用属性。在后台编译属性
class Employee
{
// Private Fields for Employee
private int id;
private string name;
//Property for id variable/field
public int EmployeeId
{
get
{
return id;
}
set
{
id = value;
}
}
//Property for name variable/field
public string EmployeeName
{
get
{
return name;
}
set
{
name = value;
}
}
}
class MyMain
{
public static void Main(string [] args)
{
Employee aEmployee = new Employee();
aEmployee.EmployeeId = 101;
aEmployee.EmployeeName = "Sundaran S";
}
}
public class DataTable
{
public class Rows
{
private string _count;
// This Count will be accessable to us but have used only "get" ie, readonly
public int Count
{
get
{
return _count;
}
}
}
public class Columns
{
private string _caption;
// Used both "get" and "set" ie, readable and writable
public string Caption
{
get
{
return _caption;
}
set
{
_caption = value;
}
}
}
}
public class Button
{
private string _text;
private string _name;
private string _someProperty;
public string Text
{
get
{
return _text;
}
set
{
_text = value;
}
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
[Browsable(false)]
public string SomeProperty
{
get
{
return _someProperty;
}
set
{
_someProperty= value;
}
}
public class Rows
{
private string _count;
public int Count
{
get
{
return CalculateNoOfRows();
}
}
public int CalculateNoOfRows()
{
// Calculation here and finally set the value to _count
return _count;
}
}
public string Name
{
// Can set debug mode inside get or set
get
{
return _name;
}
set
{
_name = value;
}
}
class SomeClass
{
int numbera; //Field
//Property
public static int numbera { get; set;}
}
System.Windows.Point[] points = new Point[1000000];
Initialize(points);
for (int i = 0; i < points.Length; i++)
{
double x = points[i].X;
double y = points[i].Y;
TransformPoint(ref x, ref y);
points[i].X = x;
points[i].Y = y;
}
internal struct MyPoint
{
internal double X;
internal double Y;
}
// ...
MyPoint[] points = new MyPoint[1000000];
Initialize(points);
// ...
for (int i = 0; i < points.Length; i++)
{
TransformPoint(ref points[i].X, ref points[i].Y);
}
// A simple example
public class student
{
public int ID;
public int passmark;
public string name;
}
public class Program
{
public static void Main(string[] args)
{
student s1 = new student();
s1.ID = -101; // here ID can't be -ve
s1.Name = null ; // here Name can't be null
}
}
public class student
{
private int _ID;
private int _passmark;
private string_name ;
// for id property
public void SetID(int ID)
{
if(ID<=0)
{
throw new exception("student ID should be greater then 0");
}
this._ID = ID;
}
public int getID()
{
return_ID;
}
}
public class programme
{
public static void main()
{
student s1 = new student ();
s1.SetID(101);
}
// Like this we also can use for Name property
public void SetName(string Name)
{
if(string.IsNullOrEmpty(Name))
{
throw new exeception("name can not be null");
}
this._Name = Name;
}
public string GetName()
{
if( string.IsNullOrEmpty(This.Name))
{
return "No Name";
}
else
{
return this._name;
}
}
// Like this we also can use for Passmark property
public int Getpassmark()
{
return this._passmark;
}
}
public class MyClass
{
private int _id;
public int ID { get { return _id; } }
public MyClass(int id)
{
_id = id;
}
}
public class MyClass
{
public int ID { get; private set; }
public MyClass(int id)
{
ID = id;
}
}
public string Name
{
get
{
return name;
}
protected set
{
name = value;
}
}
Using Getter and Setter
// field
private int _age;
// setter
public void set(int age){
if (age <=0)
throw new Exception();
this._age = age;
}
// getter
public int get (){
return this._age;
}
Now using property we can do the same thing. In the value is a key word
private int _age;
public int Age{
get{
return this._age;
}
set{
if (value <= 0)
throw new Exception()
}
}
public int Age{get;set;}
public abstract class Person
{
public abstract string Name
{
get;
set;
}
public abstract int Age
{
get;
set;
}
}
// overriden something like this
// Declare a Name property of type string:
public override string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public int MyProperty
{
get; private set;
}
private int myProperty;
public int MyProperty
{
get { return myProperty; }
}
class Room {
public string sectionOne;
public string sectionTwo;
}
Room r = new Room();
r.sectionOne = "enter";
class Room
{
private string sectionOne;
private string sectionTwo;
public string SectionOne
{
get
{
return sectionOne;
}
set
{
sectionOne = Check(value);
}
}
}
Room r = new Room();
r.SectionOne = "enter";
PROPERTY_TYPE get();
void set(PROPERTY_TYPE value);
class PropertyEmulation
{
private string MSomeValue;
public string GetSomeValue()
{
return(MSomeValue);
}
public void SetSomeValue(string value)
{
MSomeValue=value;
}
}
class OneHundredFields
{
public int Field1;
public int Field2;
...
public int Field100;
}
OneHundredFields Instance=new OneHundredFields() // Variable 'Instance' consumes 100*sizeof(int) bytes of memory.
class OneHundredProperties
{
public int Property1
{
get
{
return(1000);
}
set
{
// Empty.
}
}
public int Property2
{
get
{
return(1000);
}
set
{
// Empty.
}
}
...
public int Property100
{
get
{
return(1000);
}
set
{
// Empty.
}
}
}
OneHundredProperties Instance=new OneHundredProperties() // !!!!! Variable 'Instance' consumes 0 bytes of memory. (In fact a some bytes are consumed becasue every object contais some auxiliarity data, but size doesn't depend on number of properties).
class Name
{
public string FullName;
public int YearOfBirth;
public int Age;
}
Name name=new Name();
name.FullName="Tim Anderson";
name.YearOfBirth=1979;
name.Age=40;
name.FullName=null;
name.YearOfBirth=2200;
name.Age=-140;
class Name
{
private string MFullName="";
private int MYearOfBirth;
public string FullName
{
get
{
return(MFullName);
}
set
{
if (value==null)
{
throw(new InvalidOperationException("Error !"));
}
MFullName=value;
}
}
public int YearOfBirth
{
get
{
return(MYearOfBirth);
}
set
{
if (MYearOfBirth<1900 || MYearOfBirth>DateTime.Now.Year)
{
throw(new InvalidOperationException("Error !"));
}
MYearOfBirth=value;
}
}
public int Age
{
get
{
return(DateTime.Now.Year-MYearOfBirth);
}
}
public string FullNameInUppercase
{
get
{
return(MFullName.ToUpper());
}
}
}
class MyList
{
private string[] MBuffer;
public MyList()
{
MBuffer=new string[100];
}
public string this[int Index]
{
get
{
return(MBuffer[Index]);
}
set
{
MBuffer[Index]=value;
}
}
}
MyList List=new MyList();
List[10]="ABC";
Console.WriteLine(List[10]);
class AutoProps
{
public int Value1
{
get;
set;
}
public int Value2
{
get;
set;
}
}
internal class AutoProps
{
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int <Value1>k__BackingField;
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int <Value2>k__BackingField;
public int Value1
{
[CompilerGenerated]
get
{
return <Value1>k__BackingField;
}
[CompilerGenerated]
set
{
<Value1>k__BackingField = value;
}
}
public int Value2
{
[CompilerGenerated]
get
{
return <Value2>k__BackingField;
}
[CompilerGenerated]
set
{
<Value2>k__BackingField = value;
}
}
}