unity的C#学习——数组、字符串和结构体


C# 数组(Array)

数组是一个存储相同类型元素的固定大小的顺序集合。数组是用来存储数据的集合,通常认为数组是一个同一类型变量的集合。

所有的数组都是由连续的内存位置组成的。最低的地址对应第一个元素,最高的地址对应最后一个元素。

声明数组变量并不是声明 number0、number1、…、number99 一个个单独的变量,而是声明一个就像 numbers 这样的变量,然后使用 numbers[0]、numbers[1]、…、numbers[99] 来表示一个个单独的变量。数组中某个指定的元素是通过索引来访问的。

在 C# 中声明一个数组,可以使用语法:datatype[] arrayName;,其中:

  • datatype 用于指定被存储在数组中的元素的类型。
  • [ ] 指定数组的秩(维度)。秩指定数组的大小。
  • arrayName 指定数组的名称。

例如:

double[] balance;

1、初始化数组

声明一个数组不会在内存中初始化数组。当初始化数组变量时,可以赋值给数组。

  • 由于数组是一个引用类型,所以需要使用 new 关键字来创建数组的实例。例如:
double[] balance = new double[10];
  • 可以通过使用索引号赋值给一个单独的数组元素,比如:
double[] balance = new double[10];
balance[0] = 4500.0;
  • 可以在声明数组的同时给数组赋值,比如:
double[] balance = {
    
     2340.0, 4523.69, 3421.0};
  • 也可以创建并初始化一个数组,比如:
int [] marks = new int[5]  {
    
     99,  98, 92, 97, 95};
  • 在上述情况下,可以省略数组的大小,比如:
int [] marks = new int[]  {
    
     99,  98, 92, 97, 95};

也可以赋值一个数组变量到另一个目标数组变量中。在这种情况下,目标数组和源数组会指向相同的内存位置

int [] marks = new int[]  {
    
     99,  98, 92, 97, 95};
int[] score = marks;

当创建一个数组时,C# 编译器会根据数组类型隐式初始化每个数组元素为一个默认值。例如,int 数组的所有元素都会被初始化为 0。

2、访问数组元素

元素是通过带索引的数组名称来访问的。这是通过把元素的索引放置在数组名称后的方括号中来实现的。例如:

double salary = balance[9];

下面是一个实例,使用上面提到的三个概念,即声明、赋值、访问数组

using System;
namespace ArrayApplication
{
    
    
   class MyArray
   {
    
    
      static void Main(string[] args)
      {
    
    
         int []  n = new int[10]; /* n 是一个带有 10 个整数的数组 */
         int i,j;


         /* 初始化数组 n 中的元素 */        
         for ( i = 0; i < 10; i++ )
         {
    
    
            n[ i ] = i + 100;
         }

         /* 输出每个数组元素的值 */
         for (j = 0; j < 10; j++ )
         {
    
    
            Console.WriteLine("Element[{0}] = {1}", j, n[j]);
         }
         Console.ReadKey();
      }
   }
}

当上面的代码被编译和执行时,它会产生下列结果:

Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109

3、使用 foreach 循环遍历数组

在前面的实例中,我们使用一个 for 循环来访问每个数组元素,此外也可以使用一个 foreach 语句来遍历数组。以下实例我们使用 foreach 来遍历一个数组:

using System;

namespace ArrayApplication
{
    
    
   class MyArray
   {
    
    
      static void Main(string[] args)
      {
    
    
         int []  n = new int[10]; /* n 是一个带有 10 个整数的数组 */


         /* 初始化数组 n 中的元素 */        
         for ( int i = 0; i < 10; i++ )
         {
    
    
            n[i] = i + 100;
         }

         /* 输出每个数组元素的值 */
         foreach (int j in n )
         {
    
    
            int i = j-100;
            Console.WriteLine("Element[{0}] = {1}", i, j);
         }
         Console.ReadKey();
      }
   }
}

当上面的代码被编译和执行时,它会产生下列结果:

Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109

4、数组的细节补充

名称 定义 示例代码
多维数组 存储元素的容器,可以由一个或多个索引访问其中的元素 int[,] matrix = new int[2, 3] { {1, 2, 3}, {4, 5, 6} };
交错数组 数组的每个成员又是一个数组,每个数组的长度可以不同 int[][] jagged = new int[3][]; jagged[0] = new int[2];
传递数组给函数 函数接受数组作为参数并可以在函数内部操作数组的元素 public void ModifyArray(int[] arr) { arr[0] = 10; }
参数数组 一种特殊类型的数组,可以将任意数量的参数传递给函数 public void Print(params int[] arr) { Console.WriteLine(arr); }
Array 类 提供对数组的各种操作,如排序、搜索和复制等操作 int[] nums = new int[] { 3, 4, 1, 5, 2 }; Array.Sort(nums);

4.1 Array 类的属性

下表列出了 Array 类中一些最常用的属性:

序号 属性 描述
1 IsFixedSize 获取一个值,该值指示数组是否带有固定大小。
2 IsReadOnly 获取一个值,该值指示数组是否只读。
3 Length 获取一个 32 位整数,该值表示所有维度的数组中的元素总数。
4 LongLength 获取一个 64 位整数,该值表示所有维度的数组中的元素总数。
5 Rank 获取数组的秩(维度)。

4.2 Array 类的方法

下表列出了 Array 类中一些最常用的方法:

序号 方法 描述
1 public void Clear(int index, int length);
public void Clear(long index, long length);
根据元素的类型,设置数组中某个范围的元素为零、为 false 或者为 null。
index:要清零范围的起始索引。
length:要清零的元素数。
2 public void Copy(Array sourceArray, Array destinationArray, int length); 从数组的第一个元素开始复制某个范围的元素到另一个数组的第一个元素位置。长度由一个 32 位整数指定。
sourceArray:从其复制元素的源数组。
destinationArray:目标数组,它是一个一维数组。
length:要复制的元素数。
3 public void CopyTo(Array array, int index); 从当前的一维数组中复制所有的元素到一个指定的一维数组的指定索引位置。索引由一个 32 位整数指定。
array:一维数组,作为该方法的目标。
index:该数组中的起始位置。
4 public int GetLength(int dimension); 获取一个 32 位整数,该值表示指定维度的数组中的元素总数。
dimension:获取其长度的维度,从零开始。
5 public long GetLongLength(int dimension); 获取一个 64 位整数,该值表示指定维度的数组中的元素总数。
dimension:获取其长度的维度,从零开始。
6 public int GetLowerBound(int dimension); 获取数组中指定维度的下界。
dimension:获取其下限的维度,从零开始。
7 public Type GetType(); 获取当前实例的类型。从对象(Object)继承。
8 public int GetUpperBound(int dimension); 获取数组中指定维度的上界。
dimension:获取其上限的维度,从零开始。
9 public Object GetValue(int index); 获取一维数组中指定位置的Object。索引由一个 32 位整数指定。
index:获取其值的一维数组中的索引。
10 public static int IndexOf(Array array, object value); 搜索指定的对象,返回整个一维数组中第一个匹配项的索引,如果没有找到,则为 -1。
array:要搜索的数组。
value:要搜索的对象。
11 public static void Reverse(Array array); 逆转整个一维数组中元素的顺序。
array:要反转的一维数组。
12 public void SetValue(Object value, int index); 给一维数组中指定位置的元素设置值。索引由一个 32 位整数指定。
value:要设置的值。
index:设置该值的位置。
13 public static void Sort(Array array); 使用数组的每个元素的 IComparable 实现来排序整个一维数组中的元素。
array:要排序的一维数组。
14 public virtual string ToString(); 返回一个表示当前对象的字符串。从对象(Object)继承。

下面的程序演示了 Array 类的一些方法的用法:

using System;
namespace ArrayApplication
{
    
    
    class MyArray
    {
    
    
       
        static void Main(string[] args)
        {
    
    
            int[] list = {
    
     34, 72, 13, 44, 25, 30, 10 };

            Console.Write("原始数组: ");
            foreach (int i in list)
            {
    
    
                Console.Write(i + " ");
            }
            Console.WriteLine();
           
            // 逆转数组,序号11
            Array.Reverse(list);
            Console.Write("逆转数组: ");
            foreach (int i in list)
            {
    
    
                Console.Write(i + " ");
            }
            Console.WriteLine();
           
            // 排序数组,序号13
            Array.Sort(list);
            Console.Write("排序数组: ");
            foreach (int i in list)
            {
    
    
                Console.Write(i + " ");
            }
            Console.WriteLine();

           Console.ReadKey();
        }
    }
}

当上面的代码被编译和执行时,它会产生下列结果:

原始数组: 34 72 13 44 25 30 10
逆转数组: 10 30 25 44 13 72 34
排序数组: 10 13 25 30 34 44 72


C# 字符串(String)

在 C# 中,我们可以通过字符数组来表示字符串,但是更常见的做法是使用 string 关键字来声明一个字符串变量。string 关键字System.String 类的别名。

1、创建 String 对象

我们可以使用以下方法之一来创建 string 对象:

  • 通过给 String 变量指定一个字符串
  • 通过使用字符串串联运算符( + )
  • 通过使用 String 类构造函数
  • 通过检索属性或调用一个返回字符串的方法
  • 通过格式化方法来转换一个值或对象为它的字符串表示形式

下面的实例演示了这点:

using System;

namespace StringApplication
{
    
    
    class Program
    {
    
    
        static void Main(string[] args)
        {
    
    
           //通过给string对象指定字符串
            string fname, lname;
            fname = "Rowan";
            lname = "Atkinson";
			
			//使用字符串串联运算符,进行字符串连接
            string fullname = fname + lname;
            Console.WriteLine("Full Name: {0}", fullname);

            //通过使用 string 构造函数
            char[] letters = {
    
     'H', 'e', 'l', 'l','o' };
            string greetings = new string(letters);
            Console.WriteLine("Greetings: {0}", greetings);

            //通过join方法返回字符串
            string[] sarray = {
    
     "Hello", "From", "Tutorials", "Point" };
            string message = String.Join(" ", sarray);
            Console.WriteLine("Message: {0}", message);

            //通过格式化方法,转化值为字符串
            DateTime waiting = new DateTime(2012, 10, 10, 17, 58, 1);
            string chat = String.Format("Message sent at {0:t} on {0:D}",
            waiting);
            Console.WriteLine("Message: {0}", chat);
            Console.ReadKey() ;
        }
    }
}

在上面的代码中,演示了 C# 中关于字符串的一些基本操作和方法:

  1. 通过给 string 对象指定字符串:定义了两个 string 类型的变量 fname 和 lname,并分别初始化为 “Rowan” 和 “Atkinson”,然后使用字符串串联运算符 +,将两个字符串拼接起来,赋值给 fullname 变量。
  2. 通过使用 string 构造函数:定义了一个 char 类型的数组 letters,包含了一个字符串 “Hello” 中每个字符。然后使用 string 类的构造函数,将字符数组转换为字符串,赋值给 greetings 变量。
  3. 通过 join 方法返回字符串:定义了一个 string 类型的数组 sarray,包含了一些字符串元素。然后使用 string 类的 Join 方法,将数组中的元素用空格连接成一个字符串,赋值给 message 变量。
  4. 通过格式化方法,转化值为字符串:定义了一个 DateTime 类型的变量 waiting,表示一个日期和时间。然后使用 string 类的 Format 方法,将等待时间的时间部分和日期部分分别格式化为短时间和长日期字符串,并拼接成一个消息字符串,赋值给 chat 变量。

当上面的代码被编译和执行时,它会产生下列结果:

Full Name: RowanAtkinson
Greetings: Hello
Message: Hello From Tutorials Point
Message: Message sent at 17:58 on Wednesday, 10 October 2012

2、string类的属性

String 类包含以下属性:

属性 描述
Length 获取字符串的长度
Chars 获取或设置指定位置处的字符。

下面是一些常用 string 类的属性的代码示例:

string str = "hello world";

// 获取字符串的长度
int len = str.Length;

// 获取或设置指定位置处的字符
char ch = str[0]; // 获取第一个字符
str[0] = 'H'; // 将第一个字符设置为大写字母 'H'

3、String 类的方法

String 类有许多方法用于 string 对象的操作。下面的表格提供了一些最常用的方法:

序号 方法名称 描述
1 public static int Compare( string strA, string strB ) 比较两个指定的 string 对象,并返回一个表示它们在排列顺序中相对位置的整数。该方法区分大小写。
2 public static int Compare( string strA, string strB, bool ignoreCase ) 比较两个指定的 string 对象,并返回一个表示它们在排列顺序中相对位置的整数。但是,如果布尔参数为真时,该方法不区分大小写。
3 public static string Concat( string str0, string str1 ) 连接两个 string 对象。
4 public static string Concat( string str0, string str1, string str2 ) 连接三个 string 对象。
5 public static string Concat( string str0, string str1, string str2, string str3 ) 连接四个 string 对象。
6 public bool Contains( string value ) 返回一个表示指定 string 对象是否出现在字符串中的值。
7 public static string Copy( string str ) 创建一个与指定字符串具有相同值的新的 String 对象。
8 public void CopyTo( int sourceIndex, char[] destination, int destinationIndex, int count ) 从 string 对象的指定位置开始复制指定数量的字符到 Unicode 字符数组中的指定位置。
9 public bool EndsWith( string value ) 判断 string 对象的结尾是否匹配指定的字符串。
10 public bool Equals( string value ) 判断当前的 string 对象是否与指定的 string 对象具有相同的值。
11 public static bool Equals( string a, string b ) 判断两个指定的 string 对象是否具有相同的值。
12 public static string Format( string format, Object arg0 ) 把指定字符串中一个或多个格式项替换为指定对象的字符串表示形式。
13 public int IndexOf( char value ) 返回指定 Unicode 字符在当前字符串中第一次出现的索引,索引从 0 开始。
14 public int IndexOf( string value ) 返回指定字符串在该实例中第一次出现的索引,索引从 0 开始。
15 public int IndexOf( char value, int startIndex ) 返回指定 Unicode 字符从该字符串中指定字符位置开始搜索第一次出现的索引,索引从 0 开始。
16 public int IndexOf( string value, int startIndex ) 返回指定字符串从该实例中指定字符位置开始搜索第一次出现的索引,索引从 0 开始。
17 public int IndexOfAny( char[] anyOf ) 返回某一个指定的 Unicode 字符数组中任意字符在该实例中第一次出现的索引,索引从 0 开始。
18 public int IndexOfAny( char[] anyOf, int startIndex ) 返回某一个指定的 Unicode 字符数组中任意字符从该实例中指定字符位置开始搜索第一次出现的索引,索引从 0 开始。
19 public string Insert( int startIndex, string value ) 返回一个新的字符串,其中,指定的字符串被插入在当前 string 对象的指定索引位置。
20 public static bool IsNullOrEmpty( string value ) 指示指定的字符串是否为 null 或者是否为一个空的字符串。
21 public static string Join( string separator, string[] value ) 连接一个字符串数组中的所有元素,使用指定的分隔符分隔每个元素。
22 public static string Join( string separator, string[] value, int startIndex, int count ) 连接一个字符串数组中的指定位置开始的指定元素,使用指定的分隔符分隔每个元素。
23 public int LastIndexOf( char value ) 返回指定 Unicode 字符在当前 string 对象中最后一次出现的索引位置,索引从 0 开始。
24 public int LastIndexOf( string value ) 返回指定字符串在当前 string 对象中最后一次出现的索引位置,索引从 0 开始。
25 public string Remove( int startIndex ) 移除当前实例中的所有字符,从指定位置开始,一直到最后一个位置为止,并返回字符串。
26 public string Remove( int startIndex, int count ) 从当前字符串的指定位置开始移除指定数量的字符,并返回字符串。
27 public string Replace( char oldChar, char newChar ) 把当前 string 对象中,所有指定的 Unicode 字符替换为另一个指定的 Unicode 字符,并返回新的字符串。
28 public string Replace( string oldValue, string newValue ) 把当前 string 对象中,所有指定的字符串替换为另一个指定的字符串,并返回新的字符串。
29 public string[] Split( params char[] separator ) 返回一个字符串数组,包含当前的 string 对象中的子字符串,子字符串是使用指定的 Unicode 字符数组中的元素进行分隔的。
30 public string[] Split( char[] separator, int count ) 返回一个字符串数组,包含当前的 string 对象中的子字符串,子字符串是使用指定的 Unicode 字符数组中的元素进行分隔的。int 参数指定要返回的子字符串的最大数目。
31 public bool StartsWith( string value ) 判断字符串实例的开头是否匹配指定的字符串。
32 public string Substring(int startIndex) 提取从startIndex位置开始到字符串结尾的所有字符。
33 public string Substring(int startIndex, int length) 从startIndex位置开始提取长度为length的子字符串。
34 public char[] ToCharArray() 返回一个带有当前 string 对象中所有字符的 Unicode 字符数组。
35 public char[] ToCharArray( int startIndex, int length ) 返回一个带有当前 string 对象中所有字符的 Unicode 字符数组,从指定的索引开始,直到指定的长度为止。
36 public string ToLower() 把字符串转换为小写并返回。
37 public string ToUpper() 把字符串转换为大写并返回。
38 public string Trim() 移除当前 String 对象中的所有前导空白字符和后置空白字符。
  • 上表中添加了静态修饰符的方法就是String类方法,直接使用String.方法名调用;其余的属于实例方法,使用实例名.方法名调用。
  • 所有列出的方法都申明了返回的数据类型,更多方法待日后补充。

3.1 比较字符串实例演示

使用的方法间见序号1:

using System;

namespace StringApplication
{
    
    
   class StringProg
   {
    
    
      static void Main(string[] args)
      {
    
    
         string str1 = "This is test";
         string str2 = "This is text";

         if (String.Compare(str1, str2) == 0) //字符串比较
         {
    
    
            Console.WriteLine(str1 + " and " + str2 +  " are equal.");
         }
         else
         {
    
    
            Console.WriteLine(str1 + " and " + str2 + " are not equal.");
         }
         Console.ReadKey() ;
      }
   }
}

当上面的代码被编译和执行时,它会产生下列结果:

This is test and This is text are not equal.

3.2 字符串检索实例演示

使用的方法见序号6:

using System;

namespace StringApplication
{
    
    
   class StringProg
   {
    
    
      static void Main(string[] args)
      {
    
    
         string str = "This is test";
         if (str.Contains("test")) //检索字符串“test”是否出现在str中
         {
    
    
            Console.WriteLine("The sequence 'test' was found.");
         }
         Console.ReadKey() ;
      }
   }
}

当上面的代码被编译和执行时,它会产生下列结果:

The sequence ‘test’ was found.

3.3 获取子字符串

使用的方法间见序号32:

using System;
namespace StringApplication
{
    
    
        class StringProg
        {
    
    
                static void Main(string[] args)
                {
    
    
                        string str = "Last night I dreamt of San Pedro";
                        Console.WriteLine(str);
                        string substr = str.Substring(23);  //提取从下标为23的位置开始到字符串结尾的所有字符作为子串。
                        Console.WriteLine(substr);
                        Console.ReadKey() ;
                }
        }
}

当上面的代码被编译和执行时,它会产生下列结果:

Last night I dreamt of San Pedro
San Pedro

3.4 连接字符串

使用的方法见序号22:

using System;

namespace StringApplication
{
    
    
   class StringProg
   {
    
    
      static void Main(string[] args)
      {
    
    
         string[] starray = new string[]{
    
    "Down the way nights are dark",
         "And the sun shines daily on the mountain top",
         "I took a trip on a sailing ship",
         "And when I reached Jamaica",
         "I made a stop"};

         string str = String.Join("\n", starray); //以换行符作为分隔符,将字符串数组starray中的所有元素连接成一个以"\n"分隔的字符串
         Console.WriteLine(str);
         Console.ReadKey() ;
      }
   }
}

当上面的代码被编译和执行时,它会产生下列结果:

Down the way nights are dark
And the sun shines daily on the mountain top
I took a trip on a sailing ship
And when I reached Jamaica
I made a stop


C# 结构体(Struct)

在 C# 中,结构体是值类型数据结构。它使得一个单一变量可以存储各种数据类型的相关数据。struct 关键字用于创建结构体,通常结构体是用来代表一组记录。

假设我们想跟踪图书馆中书的动态,那可能需要跟踪每本书的以下属性:

  • Title
  • Author
  • Subject
  • Book ID

1、定义结构体

为了定义一个结构体,必须使用 struct 语句。struct 语句为程序定义了一个带有多个成员的新的数据类型。

例如,我们可以按照如下的方式声明 Book 结构:

struct Books
{
    
    
   public string title;
   public string author;
   public string subject;
   public int book_id;
};  

下面的程序演示了结构的用法:

using System;
using System.Text;
     
struct Books
{
    
    
   public string title;
   public string author;
   public string subject;
   public int book_id;
};  

public class testStructure
{
    
    
   public static void Main(string[] args)
   {
    
    

      Books Book1;        /* 声明 Book1,类型为 Books */
      Books Book2;        /* 声明 Book2,类型为 Books */

      /* book 1 详述 */
      Book1.title = "C Programming";
      Book1.author = "Nuha Ali";
      Book1.subject = "C Programming Tutorial";
      Book1.book_id = 6495407;

      /* book 2 详述 */
      Book2.title = "Telecom Billing";
      Book2.author = "Zara Ali";
      Book2.subject =  "Telecom Billing Tutorial";
      Book2.book_id = 6495700;

      /* 打印 Book1 信息 */
      Console.WriteLine( "Book 1 title : {0}", Book1.title);
      Console.WriteLine("Book 1 author : {0}", Book1.author);
      Console.WriteLine("Book 1 subject : {0}", Book1.subject);
      Console.WriteLine("Book 1 book_id :{0}", Book1.book_id);

      /* 打印 Book2 信息 */
      Console.WriteLine("Book 2 title : {0}", Book2.title);
      Console.WriteLine("Book 2 author : {0}", Book2.author);
      Console.WriteLine("Book 2 subject : {0}", Book2.subject);
      Console.WriteLine("Book 2 book_id : {0}", Book2.book_id);      

      Console.ReadKey();

   }
}

当上面的代码被编译和执行时,它会产生下列结果:

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700

2、C# 结构的特点

我们在上面已经创建了一个简单的名为Book的结构,而在 C# 中的结构与传统的 C 或 C++ 中的结构不同。C# 中的结构有以下特点:

  1. 结构可带有方法、字段、索引、属性、运算符、方法事件
public struct Person
{
    
    
    public string Name;
    public int Age;
    
    public void DisplayInfo()
    {
    
    
        Console.WriteLine($"Name: {
      
      Name}, Age: {
      
      Age}");
    }
}

在上述示例中,Person 结构体包含了两个字段 NameAge,以及一个 DisplayInfo() 方法,用于显示该结构体实例的信息。

  1. 结构可定义(有参)构造函数,但不能定义析构函数。不能为结构定义无参构造函数,因为无参构造函数(默认)是自动定义的,且不能被改变。
  • 析构函数是一种在对象销毁时自动调用的特殊函数。在C#中,由于垃圾回收机制会自动释放未使用的对象,因此在一般情况下不需要显式地编写析构函数。
public struct Person
{
    
    
    public string Name;
    public int Age;
    
    public Person(string name, int age)
    {
    
    
        Name = name;
        Age = age;
    }
}

在上述示例中,Person 结构体定义了一个有参构造函数,用于初始化 Name 和 Age 字段的值。

  1. 与类不同,结构不能继承其他的结构或类。
public struct Person
{
    
    
    // ...
}

// 错误示例:结构不能继承其他结构或类
public struct Employee : Person
{
    
    
    // ...
}
  1. 结构不能作为其他结构或类的基础结构
// 错误示例:结构不能作为其他结构或类的基础结构
public struct Person
{
    
    
    // ...
}

public class Employee : Person
{
    
    
    // ...
}
  1. 结构可实现一个或多个接口
  • interface 是 C# 中的一种类型,用于定义类或结构体的契约(contract)。它只包含成员的签名,不包含任何实现代码,因此必须由实现接口的类或结构体来提供方法的具体实现。
public interface IPerson
{
    
    
    string Name {
    
     get; set; }
    int Age {
    
     get; set; }
}

public struct Person : IPerson
{
    
    
    public string Name {
    
     get; set; }
    public int Age {
    
     get; set; }
}

在上述示例中,Person 结构体实现了 IPerson 接口。

  1. 结构成员的访问修饰符不能指定为 abstract、virtualprotected
public struct Person
{
    
    
    // 错误示例:结构成员不能指定为 abstract、virtual 或 protected
    // public abstract string Name { get; set; }
    // public virtual void DisplayInfo() {}
    // protected int Age;
    
    public string Name {
    
     get; set; }
    public void DisplayInfo()
    {
    
    
        Console.WriteLine($"Name: {
      
      Name}, Age: {
      
      Age}");
    }
}

因为结构体在创建时就是为了在外部被实例化使用。

  1. 当使用 New 操作符创建一个结构对象时,会调用适当的构造函数来创建结构。与类不同,结构可以不使用 New 操作符即可被实例化
public struct Person
{
    
    
    public string Name;
    public int Age;
}

// 使用 New 操作符创建 Person 结构体对象
var person = new Person()
{
    
    
    Name = "Tom",
    Age = 20
};

// 不使用 New 操作符即可创建 Person 结构体对象
Person person;
person.Name = "Tom";
person.Age = 20;
  1. 如果不使用 New 操作符,只有在所有的字段都被初始化之后,字段才被赋值,对象才被使用。
  • 在不使用new操作符时,如果结构体存在未被初始化的字段,则这些字段将保留默认值,其他已被初始化的字段将被赋值。这会导致结构体的行为不确定,因此最好避免这种情况。当所有字段都被初始化之后,对象才能被安全地使用。

下面是一个简单的示例代码:

struct Point
{
    
    
    public int x;
    public int y;
}

class Program
{
    
    
    static void Main(string[] args)
    {
    
    
        Point p;
        Console.WriteLine("x={0}, y={1}", p.x, p.y); // 输出未定义的值
        p.x = 10;
        Console.WriteLine("x={0}, y={1}", p.x, p.y); // 输出已定义的值
    }
}

输出结果:

x=0, y=0
x=10, y=0

可以看到,当我们尝试输出未初始化的字段时,输出的值是0,这是因为值类型int在未初始化时,所有字段都被默认初始化为0。

3、类 vs 结构

类和结构有以下几个基本的不同点:

  • 类是引用类型,结构是值类型。
  • 结构不支持继承。
  • 结构不能声明默认的无参构造函数。

结合上面的特点,我们重新编写一个包含图书信息的结构体的代码:

using System;
using System.Text;
     
struct Books
{
    
    
   private string title;
   private string author;
   private string subject;
   private int book_id;
   public void setValues(string t, string a, string s, int id)
   {
    
    
      title = t;
      author = a;
      subject = s;
      book_id =id;
   }
   public void display()
   {
    
    
      Console.WriteLine("Title : {0}", title);
      Console.WriteLine("Author : {0}", author);
      Console.WriteLine("Subject : {0}", subject);
      Console.WriteLine("Book_id :{0}", book_id);
   }

};  

public class testStructure
{
    
    
   public static void Main(string[] args)
   {
    
    

      Books Book1 = new Books(); /* 声明 Book1,类型为 Books */
      Books Book2 = new Books(); /* 声明 Book2,类型为 Books */

      /* book 1 详述 */
      Book1.setValues("C Programming",
      "Nuha Ali", "C Programming Tutorial",6495407);

      /* book 2 详述 */
      Book2.setValues("Telecom Billing",
      "Zara Ali", "Telecom Billing Tutorial", 6495700);

      /* 打印 Book1 信息 */
      Book1.display();
      
      Console.WriteLine("----------")
      
      /* 打印 Book2 信息 */
      Book2.display();

      Console.ReadKey();

   }
}

当上面的代码被编译和执行时,它会产生下列结果:

Title : C Programming
Author : Nuha Ali
Subject : C Programming Tutorial
Book_id : 6495407
----------
Title : Telecom Billing
Author : Zara Ali
Subject : Telecom Billing Tutorial
Book_id : 6495700

猜你喜欢

转载自blog.csdn.net/qq_50571974/article/details/129767529