C# 属性
C# 属性,属性是一种特殊的类成员。 我们使用预定义的 set 和 get 方法来访问和修改它们。 属性读取和写入会转换为获取和设置方法调用。 与使用自定义方法调用(例如object.GetName()
)相比,使用字段符号(例如object.Name
)访问变量更容易。 但是,就属性而言,我们仍然具有封装和信息隐藏的优势。 换句话说,属性可以保护数据免受外界干扰,同时可以方便地进行现场访问。
接口可以具有属性,但不能具有字段。
属性可以是读写的(它们既有 get 和 set 访问器),也可以是只读的(它们只有 get 访问器)或只写(它们只有 set 访问器)。
Program.
using System;
namespace SimpleProperties
{
class Person
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
}
class Program
{
static void Main(string[] args)
{
var p = new Person();
p.Name = "Jane";
Console.WriteLine(p.Name);
}
}
}
我们有一个具有一个属性的简单 Person 类。
public string Name { ... }
我们有一个称为Name
的属性。 它看起来像一个常规方法声明。 不同之处在于,它具有称为get
和set
的特定访问器。
get { return _name; } set { _name = value; }
get
属性访问器用于返回属性值,set
访问器用于分配新值。 value
关键字用于定义由设置索引器分配的值。
var p = new Person(); p.Name = "Jane"; Console.WriteLine(p.Name);
我们创建Person
类的实例。 我们使用字段符号访问成员字段。
$ dotnet run Jane
这是该计划的结果。
C# 只读属性
可以创建只读属性。 为了创建一个只读属性,我们省略了 set 访问器,在实现中仅提供了 get 访问器。
Program.
using System;
namespace Readonly
{
class Person
{
private string _name = "Jane";
public string Name
{
get { return _name; }
}
}
class Program
{
static void Main(string[] args)
{
var p = new Person();
// p.Name = "Beky";
Console.WriteLine(p.Name);
}
}
}
在前面的示例中,我们演示了只读属性的使用。
private string _name = "Jane";
我们立即初始化成员,因为以后不可能。
public string Name
{
get { return _name; }
}
通过仅提供一个 get 访问器,使该属性为只读。
// p.Name = "Beky";
现在此行已注释。 我们无法更改属性。 如果我们取消注释该行,则 C# 编译器将发出以下错误:Program.(21,13): error 0200: Property or indexer 'Person.Name' cannot be assigned to -- it is read only
。
C# 自动实现的属性
C# 具有自动实现或自动属性。 在软件项目中,有许多简单属性只能设置或获取一些简单值。 为了简化编程并简化代码,创建了自动属性。 注意,我们不能在所有情况下都使用自动属性。 仅适用于简单的。
Program. using System; namespace Autoimplemented { class Person { public string Name { get; set; } public int Age { get; set; } } class Program { static void Main(string[] args) { var p = new Person(); p.Name = "Jane"; p.Age = 17; Console.WriteLine($"{p.Name} is {p.Age} years old"); } } }
该代码要短得多。 我们有一个Person
类,其中有两个属性:Name
和Age
。
public string Name { get; set; } public int Age { get; set; }
在这里,我们有两个自动属性。 没有访问器的实现,也没有成员字段。 编译器将为我们完成其余的工作。
var p = new Person(); p.Name = "Jane"; p.Age = 17; Console.WriteLine($"{p.Name} is {p.Age} years old");
我们通常照常使用这些属性。
$ dotnet run Jane is 17 years old
这是示例的输出。
表达式主体定义
从 C# 7.0 开始,可以使用表达式主体定义简化属性。 表达式主体定义由=>
符号组成,后跟要分配给该属性或从该属性检索的表达式。
Program. using System; namespace ExpBodyDef { class User { string name; string occupation; public User(string name, string occupation) { this.name = name; this.occupation = occupation; } public string Name { get => name; set => name = value; } public string Occupation { get => occupation; set => occupation = value; } } class Program { static void Main(string[] args) { var u = new User("John Doe", "gardener"); Console.WriteLine($"{u.Name} is a {u.Occupation}"); } } }
在示例中,我们使用表达式主体定义来定义User
类的属性。
$ dotnet run John Doe is a gardener
这是输出。
其他注意事项
我们可以使用public
,private
或protected
等访问修饰符标记属性。 属性也可以是static
,abstract
,virtual
和sealed
。 它们的用法与常规方法相同。
Program. using System; namespace OtherNotes { class Base { protected string _name = "Base class"; public virtual string Name { set { _name = value; } get { return _name; } } } class Derived : Base { protected new string _name = "Derived class"; public override string Name { set { _name = value; } get { return _name; } } } class Program { static void Main(string[] args) { var bs = new Base(); var dr = new Derived(); Console.WriteLine(bs.Name); Console.WriteLine(dr.Name); } } }
在前面的示例中,我们定义了一个虚拟属性,并在Derived
类中将其覆盖。
public virtual string Name { set { _name = value; } get { return _name; } }
名称属性用virtual
关键字标记。
protected new string _name = "Derived class";
我们将成员隐藏在“派生”类中。 为了消除编译器警告,我们使用new
关键字。
public override string Name { set { _name = value; } get { return _name; } }
在这里,我们重写了Base
类的Name
属性。
结构 (程序优化)
C# 结构,结构是值类型。 该类型由struct
关键字定义。 结构与类非常相似。 它们在某些方面有所不同。 结构旨在表示轻量级对象,例如Point
,Rectangle
,Color
等。 在许多情况下,结构可能比类更有效。 结构是值类型,并在堆栈上创建。 注意,像int
,bool
,float
之类的原始数据类型在技术上都是struct
类型。
所有struct
类型都继承自System.ValueType
,并且继承自System.Object
。 结构从来都不是抽象的,它们总是被隐式密封的。 因此结构类型不支持继承。 因此,不能将struct
数据成员声明为受保护的。 struct
定义不允许使用抽象修饰符和密封修饰符。 不允许struct
声明无参数的构造函数。
结构还可以包含构造函数,常量,字段,方法,属性,索引器,运算符,事件和嵌套类型。 但是,如果我们需要实现更多这些功能,则可以考虑使用一个类。 结构可以实现接口。 struct
可以用作nullable
类型,并且可以分配为空值。
简单结构示例
以下示例创建一个简单的结构。
Program. using System; namespace SimpleStructure { public struct Point { private int x; private int y; public Point(int x, int y) { this.x = x; this.y = y; } public override string ToString() { return String.Format("Point x:{0}, y:{1}", x, y); } } class Program { static void Main(string[] args) { var p = new Point(2, 5); Console.WriteLine(p); } } }
该示例创建一个Point
结构。 这个点也可以用一个类来表示,但是有了struct
,我们的效率更高了。 特别是如果我们处理了很多问题。
public struct Point { ... }
该结构用struct
关键字声明。
public override string ToString() { return String.Format("Point x:{0}, y:{1}", x, y); }
struct
类型不支持继承。 但是,我们可以对方法使用override
关键字,struct
类型隐式地从中继承。 ToString()
方法就是这种情况。
var p = new Point(2, 5); Console.WriteLine(p);
我们创建Point
结构,并在其上调用ToString()
方法。
$ dotnet run Point x:2, y:5
这是示例的输出。
没有new
关键字
可以创建不带new
关键字的struct
类型的实例。
Program. using System; namespace NoNewKeyword { public struct Person { public string name; public int age; } class Program { static void Main(string[] args) { Person p; p.name = "Jane"; p.age = 17; Console.WriteLine("{0} is {1} years old", p.name, p.age); } } }
我们有一个Person
结构,其中有两个公共成员。
Person p;
首先,我们声明一个Person
结构。
p.name = "Jane"; p.age = 17;
稍后我们用一些数据初始化结构。
$ dotnet run Jane is 17 years old
这是程序的输出。
C# 结构是值类型
结构类型是值类型。 它们是在堆栈上创建的。 创建值类型时,仅在内存中分配了一个空间来存储值。 值类型的分配将复制该值。
Program. using System; namespace ValueTypes { public struct Person { public Person(string name, int age) : this() { this.Name = name; this.Age = age; } public string Name { get; set; } public int Age { get; set; } public override string ToString() { return String.Format("{0} is {1} years old", Name, Age); } } class Program { static void Main(string[] args) { var p1 = new Person("Beky", 18); var p2 = p1; Console.WriteLine(p2); p2.Name = "Jane"; p2.Age = 17; Console.WriteLine(p2); Console.WriteLine(p1); } } }
我们有一个带有两个数据成员的Person
结构。 我们有两个参数的构造函数,我们也使用自动属性。
public string Name { get; set; } public int Age { get; set; }
可以在struct
类型中使用自动属性。
var p1 = new Person("Beky", 18);
var p2 = p1;
在这里,我们创建一个struct
。 然后将创建的struct
分配给另一个struct
。 我们创建该结构的副本。
p2.Name = "Jane"; p2.Age = 17;
我们更改第二个结构的数据。 第一个不受影响,因为我们正在处理原始struct
类型的副本。
$ dotnet run Beky is 18 years old Jane is 17 years old Beky is 18 years old
基本类型是结构
像int
,float
或bool
之类的原始数据类型是内部结构。 这不同于 C++ 或 Java 之类的语言。
Program. using System; public class PrimitiveTypes { static void Main() { float x = 12.3f; int y = 34; bool z = false; Console.WriteLine(x.GetType()); Console.WriteLine(y.GetType()); Console.WriteLine(z.GetType()); } }
我们有三个变量:float,int
和bool
。 我们对它们每个调用GetType()
方法。
Console.WriteLine(x.GetType());
我们在浮点值上调用GetType()
方法。 每个结构都隐式继承自包含GetType()
方法的System.ValueType
类。
$ dotnet run System.Single System.Int32 System.Boolean
这是示例的输出。 我们可以在文档中查找这些类型是结构。
标签:Name,get,C#,name,属性,public,string,结构 From: https://www.cnblogs.com/lvbjj/p/18115851