C# 对象
最后修改于 2023 年 7 月 5 日
在本文中,我们将展示如何在 C# 中创建和使用对象。
对象是 C# 程序的基本构建块。
对象是数据和方法的组合。数据和方法被称为对象的成员。在 C# 中,所有类型都是对象。
对象从模板创建。 模板使用 class
、struct
或 record
关键字定义。 我们说我们从这些模板创建对象实例。
对象的属性和方法使用点运算符访问。 构造函数是用于创建对象的专用方法。
C# 结构体对象
结构是一种值类型。 该类型使用 struct
关键字定义。 结构旨在表示轻量级对象,如 Point、Rectangle、Color 等。
var p = new Point(2, 5); Console.WriteLine(p); 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 $"Point x:{x}, y:{y}"; } }
在该程序中,我们从一个 Point
结构体创建一个轻量级对象。 我们还重写了 ToString
方法,该方法给出了该对象的可读表示。
$ dotnet run Point x:2, y:5
原始类型是对象
C# 原始类型是对象。 在底层,它们是结构体。
float x = 12.3f; int y = 34; bool z = false; Console.WriteLine(x.GetType()); Console.WriteLine(y.GetType()); Console.WriteLine(z.GetType()); Console.WriteLine(y.Equals(34));
我们将三个原始类型分配给三个变量。
Console.WriteLine(x.GetType()); Console.WriteLine(y.GetType()); Console.WriteLine(z.GetType()); Console.WriteLine(y.Equals(34));
float、int 和 bool 类型都是对象。 我们在这些对象上调用 GetType
和 Equals
方法。
C# 对象的 ToString 方法
每个对象都有一个 ToString
方法。它返回对象的可读表示。默认实现返回 Object
类型的完全限定名称。请注意,当我们使用对象作为参数调用 Console.WriteLine
方法时,会调用 ToString
。
var b = new Being(); var o = new Object(); Console.WriteLine(o.ToString()); Console.WriteLine(b.ToString()); Console.WriteLine(b); class Being { public override string ToString() { return "This is Being class"; } }
我们有一个 Being
类,我们在其中重写 ToString
方法的默认实现。
public override string ToString() { return "This is Being class"; }
创建的每个类都继承自基类 object
。 ToString
方法属于这个 object 类。我们使用 override
关键字来告知我们正在重写一个方法。
var b = new Being(); var o = new Object();
我们创建一个自定义定义的对象和一个内置对象。
Console.WriteLine(o.ToString()); Console.WriteLine(b.ToString());
我们在两个对象上调用 ToString
方法。
Console.WriteLine(b);
正如我们之前指定的那样,将一个对象作为参数传递给 Console.WriteLine
将调用其 ToString
方法。这次,我们隐式地调用了该方法。
$ dotnet run System.Object This is Being class This is Being class
C# 对象属性
对象属性是捆绑在类实例中的数据。 对象属性被称为实例变量或成员字段。 实例变量是在对象模板中定义的变量,模板中的每个对象都有一个单独的副本。
var u1 = new User(); u1.name = "John Doe"; u1.occupation = "gardener"; var u2 = new User(); u2.name = "Roger Roe"; u2.occupation = "driver"; Console.WriteLine(u1); Console.WriteLine(u2); class User { public string? name; public string? occupation; public override string ToString() { return $"{name} is a {occupation}"; } }
我们有一个带有两个成员字段的 User
类。
class User { public string? name; public string? occupation; public override string ToString() { return $"{name} is a {occupation}"; } }
我们声明一个 name 和 occupation 成员字段。 public
关键字指定成员字段在类块外部可访问。
var u1 = new User(); u1.name = "John Doe"; u1.occupation = "gardener";
我们创建 User
类的一个实例,并设置 name 和 occupation 属性。 我们使用点运算符来访问对象的属性。
Console.WriteLine(u1); Console.WriteLine(u2);
我们将两个用户对象打印到控制台。
$ dotnet run John Doe is a gardener Roger Roe is a driver
C# 对象方法
方法是在对象模板主体内定义的函数。 它们用于对对象的属性执行操作。
var c = new Circle(); c.SetRadius(5); Console.WriteLine(c.Area()); class Circle { private int radius; public void SetRadius(int radius) { this.radius = radius; } public double Area() { return this.radius * this.radius * Math.PI; } }
在代码示例中,我们有一个 Circle 类。我们定义了两个方法。
private int radius;
我们有一个成员字段。 它是圆的半径。 private
关键字是一个访问修饰符。 它表示变量对外界是受限制的。 如果我们要从外部修改此变量,我们必须使用公开可用的 SetRadius
方法。
public void SetRadius(int radius) { this.radius = radius; }
这是 SetRadius
方法。 this
变量是一个特殊的变量,我们使用它从方法中访问成员字段。 this.radius
是一个实例变量,而 radius 是一个局部变量,仅在 SetRadius
方法内部有效。
var c = new Circle(); c.SetRadius(5);
我们创建 Circle
类的一个实例,并通过在 circle 对象上调用 SetRadius
方法来设置其半径。 我们使用点运算符来调用该方法。
public double Area() { return this.radius * this.radius * Math.PI; }
Area
方法返回圆的面积。Math.PI
是一个内置常量。
$ dotnet run 78.5398163397448
C# 对象构造函数
构造函数用于初始化字段。
var name = "Lenka"; var dob = new DateTime(1990, 3, 5); var u = new User(name, dob); Console.WriteLine(u); class User { private DateTime Born; private string Name; public User(string Name, DateTime Born) { this.Name = Name; this.Born = Born; } public override string ToString() => $"{this.Name} was born on {this.Born.ToShortDateString()}"; }
我们有一个 User
类的构造函数。
var u = new User(name, dob);
我们创建 User
对象,并向其构造函数传递两个值。 这是调用对象构造函数的时间。
public User(string Name, DateTime Born) { this.Name = Name; this.Born = Born; }
在构造函数方法内部,我们初始化两个属性:Name
和 Born
。 由于属性和构造函数参数的名称相同,因此 this
关键字是强制性的。 它用于引用类的属性。
$ dotnet run Lenka was born on 3/5/1990
C# 对象自动实现的属性
C# 具有自动实现或自动属性。 使用自动属性,编译器透明地为我们提供支持字段。
var u = new User(); u.Name = "John Doe"; u.Occupation = "gardener"; Console.WriteLine($"{u.Name} is a {u.Occupation}"); struct User { public string? Name { get; set; } public string? Occupation { get; set; } }
这段代码更短。 我们有一个 User
结构体,其中有两个属性:Name
和 Occupation
。
var u = new User(); u.Name = "John Doe"; u.Occupation = "gardener"; Console.WriteLine($"{u.Name} is a {u.Occupation}");
我们通常像往常一样使用这些属性。
public string? Name { get; set; } public string? Occupation { get; set; }
这里我们有两个自动属性。 没有访问器的实现,也没有成员字段。 编译器为我们自动生成它们。
$ dotnet run John Doe is a gardener
C# 对象解构
解构是将类型解包为单个部分; 例如,将元组解包为其项目或将对象解包为其属性。
要解构类实例,我们必须实现 Deconstruct
方法。
var u = new User("John", "Doe", "gardener"); var (fname, lname, occupation) = u; Console.WriteLine($"{fname} {lname} is a(n) {occupation}"); var (fn, ln) = u; Console.WriteLine($"{fn} {ln}"); class User { string FirstName { get; set; } string LastName { get; set; } string Occupation { get; set; } public User(string fname, string lname, string occupation) { FirstName = fname; LastName = lname; Occupation = occupation; } public void Deconstruct(out string fname, out string lname) { fname = FirstName; lname = LastName; } public void Deconstruct(out string fname, out string lname, out string occupation) { fname = FirstName; lname = LastName; occupation = Occupation; } }
我们可以有多个 Deconstruct
方法。
var u = new User("John", "Doe", "gardener"); var (fname, lname, occupation) = u;
在这里,我们将 User
类型解构为三个变量。
var (fn, ln) = u; Console.WriteLine($"{fn} {ln}");
在这里,我们将用户解构为两个变量。
public void Deconstruct(out string fname, out string lname) { fname = FirstName; lname = LastName; }
被解构的变量具有 out
修饰符。
$ dotnet run John Doe is a(n) gardener John Doe
C# 记录对象
记录是一种引用类型,其主要目的是保存数据。 记录允许我们快速创建对象。
var users = new List<User> { new ("John", "Doe", 1230), new ("Lucy", "Novak", 670), new ("Ben", "Walter", 2050), new ("Robin", "Brown", 2300), new ("Amy", "Doe", 1250), new ("Joe", "Draker", 1190), new ("Janet", "Doe", 980), new ("Albert", "Novak", 1930), }; users.ForEach(Console.WriteLine); Console.WriteLine(users[0].FirstName); Console.WriteLine(users[0].LastName); Console.WriteLine(users[0].Salary); record User(string FirstName, string LastName, int Salary);
在该示例中,我们有一个 User
对象列表。
var users = new List<User> { new ("John", "Doe", 1230), new ("Lucy", "Novak", 670), new ("Ben", "Walter", 2050), new ("Robin", "Brown", 2300), new ("Amy", "Doe", 1250), new ("Joe", "Draker", 1190), new ("Janet", "Doe", 980), new ("Albert", "Novak", 1930), };
创建了一个对象列表。 当类型已知时,目标类型的新表达式不需要构造函数的类型规范。 编译器从赋值操作的左侧推断类型。
Console.WriteLine(users[0].FirstName); Console.WriteLine(users[0].LastName); Console.WriteLine(users[0].Salary);
我们使用点运算符访问记录对象的三个属性。
record User(string FirstName, string LastName, int Salary);
记录在一行中定义。 记录为我们自动生成多个方法,包括 Object.Equals
和 Object.ToString
。
$ dotnet run User { FirstName = John, LastName = Doe, Salary = 1230 } User { FirstName = Lucy, LastName = Novak, Salary = 670 } User { FirstName = Ben, LastName = Walter, Salary = 2050 } User { FirstName = Robin, LastName = Brown, Salary = 2300 } User { FirstName = Amy, LastName = Doe, Salary = 1250 } User { FirstName = Joe, LastName = Draker, Salary = 1190 } User { FirstName = Janet, LastName = Doe, Salary = 980 } User { FirstName = Albert, LastName = Novak, Salary = 1930 } John Doe 1230
来源
在本文中,我们使用 C# 中的对象。
作者
列出所有 C# 教程。