服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - 讲解C#面相对象编程中的类与对象的特性与概念

讲解C#面相对象编程中的类与对象的特性与概念

2021-11-09 12:00C#教程网 C#

这篇文章主要介绍了C#面相对象编程中的类与对象的特性与概念,OOP面向对象语言相对C语言这样面相过程的语言来说具有类和对象以及方法这样的特性,需要的朋友可以参考下


“类”是一种构造,通过使用该构造,您可以将其他类型的变量、方法和事件组合在一起,从而创建自己的自定义类型。类就像一个蓝图,它定义类型的数据和行为。如果类没有声明为静态类,客户端代码就可以创建赋给变量的“对象”或“实例”,从而使用该类。在对变量的所有引用都超出范围之前,该变量始终保持在内存中。所有引用都超出范围时,CLR 将标记该变量以供垃圾回收。如果类声明为静态类,则内存中只存在一个副本,并且客户端代码只能通过该类自身而不是“实例变量”访问该类。
声明类
类使用 class 关键字进行声明,如下面的示例所示:

?
1
2
3
4
public class Customer
{
  //Fields, properties, methods and events go here...
}

class 关键字前面是访问级别。由于在该例中使用 public,因此任何人都可以基于该类创建对象。类的名称位于 class 关键字的后面。定义的其余部分是类的主体,用于定义行为和数据。类的字段、属性、方法和事件统称为“类成员”。
创建对象
尽管有时类和对象可互换,但它们是不同的概念。类定义对象的类型,但它不是对象本身。对象是基于类的具体实体,有时称为类的实例。
通过使用 new 关键字(后跟对象将基于的类的名称)可以创建对象,如下所示:

?
1
Customer object1 = new Customer();

创建类的实例后,将向程序员传递回对该对象的引用。在前面的示例中,object1 是对基于 Customer 的对象的引用。此引用引用新对象,但不包含对象数据本身。实际上,可以在根本不创建对象的情况下创建对象引用:

?
1
Customer object2;

建议不要创建像这样的不引用对象的对象引用,因为在运行时通过这样的引用来访问对象的尝试将会失败。但是,可以创建这样的引用来引用对象,方法是创建新对象,或者将它分配给现有的对象,如下所示:

?
1
2
Customer object3 = new Customer();
Customer object4 = object3;

此代码创建了两个对象引用,它们引用同一个对象。因此,通过 object3 对对象所做的任何更改都将反映在随后使用的 object4 中。由于基于类的对象是按引用来引用的,因此类称为引用类型。
类继承
继承是通过使用“派生”来实现的,而派生意味着类是使用“基类”声明的,它的数据和行为从基类继承。通过在派生的类名后面追加冒号和基类名称,可以指定基类,如下所示:

?
1
2
3
4
5
public class Manager : Employee
{
  // Employee fields, properties, methods and events are inherited
  // New Manager fields, properties, methods and events go here...
}

当类声明基类时,它继承基类除构造函数以外的所有成员。
与 C++ 不同,C# 中的类只能直接从一个基类继承。但是,因为基类自身也可能继承自另一个类,所以类可以间接继承多个基类。而且,一个类可以直接实现一个以上的接口。
类可以声明为抽象类。抽象类包含具有签名定义但没有实现的抽象方法。抽象类不能进行实例化。只能通过实现抽象方法的派生类使用抽象类。相比之下,密封类不允许其他类从其派生。
类定义可在不同的源文件之间进行拆分。
描述
下面的示例中定义了一个公共类,其中包含一个字段、一个方法和一个称为构造函数的特殊方法。有关更多信息,请参见构造函数(C# 编程指南)。然后使用 new 关键字将该类实例化。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class Person
{
  // Field
  public string name;
 
  // Constructor that takes no arguments.
  public Person()
  {
    name = "unknown";
  }
 
  // Constructor that takes one argument.
  public Person(string nm)
  {
    name = nm;
  }
 
  // Method
  public void SetName(string newName)
  {
    name = newName;
  }
}
class TestPerson
{
  static void Main()
  {
    // Call the constructor that has no parameters.
    Person person1 = new Person();
    Console.WriteLine(person1.name);
 
    person1.SetName("John Smith");
    Console.WriteLine(person1.name);
 
    // Call the constructor that has one parameter.
    Person person2 = new Person("Sarah Jones");
    Console.WriteLine(person2.name);
 
    // Keep the console window open in debug mode.
    Console.WriteLine("Press any key to exit.");
    Console.ReadKey();
  }
}

输出:

?
1
2
3
unknown
John Smith
Sarah Jones

对象
类或结构定义的作用类似于蓝图,指定该类型可以进行哪些操作。从本质上说,对象是按照此蓝图分配和配置的内存块。程序可以创建同一个类的多个对象。对象也称为实例,可以存储在命名变量中,也可以存储在数组或集合中。使用这些变量来调用对象方法及访问对象公共属性的代码称为客户端代码。在 C# 等面向对象的语言中,典型的程序由动态交互的多个对象组成。

结构实例。. 选件类实例
由于类是引用类型,因此类对象的变量引用该对象在托管堆上的地址。如果将同一类型的第二个对象分配给第一个对象,则两个变量都引用该地址的对象。这一点将在本主题后面部分进行更详细的讨论。
类的实例是使用 new 运算符创建的。在下面的示例中,Person 为类型,person1 和 person 2 为该类型的实例(即对象)。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class Person
{
  public string Name { get; set; }
  public int Age { get; set; }
  public Person(string name, int age)
  {
    Name = name;
    Age = age;
  }
  //Other properties, methods, events...
}
 
class Program
{
  static void Main()
  {
    Person person1 = new Person("Leopold", 6);
    Console.WriteLine("person1 Name = {0} Age = {1}", person1.Name, person1.Age);
 
    // Declare new person, assign person1 to it.
    Person person2 = person1;
 
    //Change the name of person2, and person1 also changes.
    person2.Name = "Molly";
    person2.Age = 16;
 
    Console.WriteLine("person2 Name = {0} Age = {1}", person2.Name, person2.Age);
    Console.WriteLine("person1 Name = {0} Age = {1}", person1.Name, person1.Age);
 
    // Keep the console open in debug mode.
    Console.WriteLine("Press any key to exit.");
    Console.ReadKey();
 
  }
}

输出:

?
1
2
3
person1 Name = Leopold Age = 6
person2 Name = Molly Age = 16
person1 Name = Molly Age = 16

由于结构是值类型,因此结构对象的变量具有整个对象的副本。结构的实例也可以使用 new 运算符来创建,但这不是必需的,如下面的示例所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public struct Person
{
  public string Name;
  public int Age;
  public Person(string name, int age)
  {
    Name = name;
    Age = age;
  }
}
 
public class Application
{
  static void Main()
  {
    // Create struct instance and initialize by using "new".
    // Memory is allocated on thread stack.
    Person p1 = new Person("Alex", 9);
    Console.WriteLine("p1 Name = {0} Age = {1}", p1.Name, p1.Age);
 
    // Create new struct object. Note that struct can be initialized
    // without using "new".
    Person p2 = p1;
 
    // Assign values to p2 members.
    p2.Name = "Spencer";
    p2.Age = 7;
    Console.WriteLine("p2 Name = {0} Age = {1}", p2.Name, p2.Age);
 
    // p1 values remain unchanged because p2 is copy.
    Console.WriteLine("p1 Name = {0} Age = {1}", p1.Name, p1.Age);
 
    // Keep the console open in debug mode.
    Console.WriteLine("Press any key to exit.");
    Console.ReadKey();
  }
}

输出:

?
1
2
3
p1 Name = Alex Age = 9
p2 Name = Spencer Age = 7
p1 Name = Alex Age = 9

p1 和 p2 的内存在线程堆栈上进行分配。该内存随声明它的类型或方法一起回收。这就是在赋值时复制结构的一个原因。相比之下,当对类实例对象的所有引用都超出范围时,为该类实例分配的内存将由公共语言运行时自动回收(垃圾回收)。无法像在 C++ 中那样明确地销毁类对象。

对象标识与. 值相等性
在比较两个对象是否相等时,首先必须明确您是想知道两个变量是否表示内存中的同一对象,还是想知道这两个对象的一个或多个字段的值是否相等。如果您要对值进行比较,则必须考虑这两个对象是值类型(结构)的实例,还是引用类型(类、委托、数组)的实例。
若要确定两个类实例是否引用内存中的同一位置(意味着它们具有相同的标识),可使用静态 Equals 方法。(System.Object 是所有值类型和引用类型的隐式基类,其中包括用户定义的结构和类。)
若要确定两个结构实例中的实例字段是否具有相同的值,可使用 ValueType.Equals 方法。由于所有结构都隐式继承自 System.ValueType,因此可以直接在对象上调用该方法,如下面的示例所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Person is defined in the previous example.
 
//public struct Person
//{
//  public string Name;
//  public int Age;
//  public Person(string name, int age)
//  {
//    Name = name;
//    Age = age;
//  }
//}
 
Person p1 = new Person("Wallace", 75);
Person p2;
p2.Name = "Wallace";
p2.Age = 75;
 
if (p2.Equals(p1))
  Console.WriteLine("p2 and p1 have the same values.");

输出:

?
1
p2 and p1 have the same values.

Equals 的 System.ValueType 实现使用反射,因为它必须能够确定任何结构中有哪些字段。在创建您自己的结构时,重写 Equals 方法可以提供针对您的类型的高效求等算法。

延伸 · 阅读

精彩推荐
  • C#C#微信公众号与订阅号接口开发示例代码

    C#微信公众号与订阅号接口开发示例代码

    这篇文章主要介绍了C#微信公众号与订阅号接口开发示例代码,结合实例形式简单分析了C#针对微信接口的调用与处理技巧,需要的朋友可以参考下...

    smartsmile20127762021-11-25
  • C#VS2012 程序打包部署图文详解

    VS2012 程序打包部署图文详解

    VS2012虽然没有集成打包工具,但它为我们提供了下载的端口,需要我们手动安装一个插件InstallShield。网上有很多第三方的打包工具,但为什么偏要使用微软...

    张信秀7712021-12-15
  • C#深入理解C#的数组

    深入理解C#的数组

    本篇文章主要介绍了C#的数组,数组是一种数据结构,详细的介绍了数组的声明和访问等,有兴趣的可以了解一下。...

    佳园9492021-12-10
  • C#利用C#实现网络爬虫

    利用C#实现网络爬虫

    这篇文章主要介绍了利用C#实现网络爬虫,完整的介绍了C#实现网络爬虫详细过程,感兴趣的小伙伴们可以参考一下...

    C#教程网11852021-11-16
  • C#C#设计模式之Strategy策略模式解决007大破密码危机问题示例

    C#设计模式之Strategy策略模式解决007大破密码危机问题示例

    这篇文章主要介绍了C#设计模式之Strategy策略模式解决007大破密码危机问题,简单描述了策略模式的定义并结合加密解密算法实例分析了C#策略模式的具体使用...

    GhostRider10972022-01-21
  • C#三十分钟快速掌握C# 6.0知识点

    三十分钟快速掌握C# 6.0知识点

    这篇文章主要介绍了C# 6.0的相关知识点,文中介绍的非常详细,通过这篇文字可以让大家在三十分钟内快速的掌握C# 6.0,需要的朋友可以参考借鉴,下面来...

    雨夜潇湘8272021-12-28
  • C#SQLite在C#中的安装与操作技巧

    SQLite在C#中的安装与操作技巧

    SQLite,是一款轻型的数据库,用于本地的数据储存。其优点有很多,下面通过本文给大家介绍SQLite在C#中的安装与操作技巧,感兴趣的的朋友参考下吧...

    蓝曈魅11162022-01-20
  • C#如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

    如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

    这篇文章主要给大家介绍了关于如何使用C#将Tensorflow训练的.pb文件用在生产环境的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴...

    bbird201811792022-03-05