1.索引器的使用以及理解索引器的重載,索引器的鏈式調(diào)用
在C#中,索引器(Indexer)是一種特殊的屬性,它允許您使用數(shù)組的索引方式來訪問類的實例。索引器使得類的對象可以像數(shù)組一樣通過索引來訪問其元素。這在處理集合或列表時特別有用,因為它提供了一種統(tǒng)一的方式來訪問集合中的元素。
索引器的語法如下:
public class MyClass
{
private int[] _items; // 假設(shè)我們有一個整數(shù)數(shù)組
// 索引器的定義
public int this[int index]
{
get
{
// 獲取操作
if (index < 0 || index >= _items.Length)
{
throw new IndexOutOfRangeException("索引超出范圍。");
}
return _items[index];
}
set
{
// 設(shè)置操作
if (index < 0 || index >= _items.Length)
{
throw new IndexOutOfRangeException("索引超出范圍。");
}
_items[index] = value;
}
}
}
class Program
{
static void Main(string[] args)
{
MyClass myClass = new MyClass();
myClass._items = new int[] { 1, 2, 3, 4, 5 };
// 使用索引器訪問元素
Console.WriteLine(myClass[2]); // 輸出: 3
// 使用索引器設(shè)置元素值
myClass[2] = 10;
Console.WriteLine(myClass[2]); // 輸出: 10
}
}
在這個例子中,MyClass 有一個名為 _items 的私有整數(shù)數(shù)組。我們定義了一個名為 this 的索引器,它允許我們通過索引來訪問和設(shè)置 _items 數(shù)組的元素。索引器的 get 訪問器用于獲取指定索引處的值,而 set 訪問器用于設(shè)置該索引處的值。
用戶可以通過 myClass[2] 這樣的語法來訪問或設(shè)置 _items 數(shù)組的第三個元素(索引從0開始)。這種方式與訪問數(shù)組元素的方式非常相似,使得類的對象可以像數(shù)組一樣被操作。
需要注意的是,索引器的名稱 this 是特殊的,它表示索引器。在索引器的定義中,我們使用 int index 作為參數(shù)來表示索引,您可以根據(jù)需要使用不同的數(shù)據(jù)類型作為索引。此外,索引器可以有多個參數(shù),以便實現(xiàn)多維索引。
如果您的屬性是一個三維數(shù)組,您需要在索引器中定義三個維度的索引。以下是一個簡單的例子,展示了如何為三維數(shù)組定義索引器:
public class MyClass
{
private int[,,] _items; // 三維整數(shù)數(shù)組
// 三維索引器的定義,使用index1, index2, index3作為參數(shù)名
public int this[int index1, int index2, int index3]
{
get
{
// 獲取操作
if (index1 < 0 || index1 >= _items.GetLength(0) ||
index2 < 0 || index2 >= _items.GetLength(1) ||
index3 < 0 || index3 >= _items.GetLength(2))
{
throw new IndexOutOfRangeException("索引超出范圍。");
}
return _items[index1, index2, index3];
}
set
{
// 設(shè)置操作
if (index1 < 0 || index1 >= _items.GetLength(0) ||
index2 < 0 || index2 >= _items.GetLength(1) ||
index3 < 0 || index3 >= _items.GetLength(2))
{
throw new IndexOutOfRangeException("索引超出范圍。");
}
_items[index1, index2, index3] = value;
}
}
// 初始化三維數(shù)組的方法
public void InitializeArray(int size1, int size2, int size3)
{
_items = new int[size1, size2, size3];
// 初始化數(shù)組或執(zhí)行其他操作
}
}
class Program
{
static void Main(string[] args)
{
MyClass myClass = new MyClass();
myClass.InitializeArray(3, 3, 3); // 初始化一個3x3x3的三維數(shù)組
// 使用三維索引器訪問元素
Console.WriteLine(myClass[1, 1, 1]); // 輸出數(shù)組中的某個元素
// 使用三維索引器設(shè)置元素值
myClass[1, 1, 1] = 10;
Console.WriteLine(myClass[1, 1, 1]); // 輸出修改后的元素值
}
}
在這個例子中,MyClass 有一個名為 _items 的三維整數(shù)數(shù)組。我們定義了一個三維索引器,它接受三個整數(shù)參數(shù):index1、index2 和 index3。這些參數(shù)分別代表三維數(shù)組的三個維度。在 get 和 set 訪問器中,我們使用這些參數(shù)來訪問或設(shè)置數(shù)組中的特定元素。
InitializeArray 方法用于初始化三維數(shù)組,您可以根據(jù)需要設(shè)置數(shù)組的大小。在 Main 方法中,我們創(chuàng)建了 MyClass 的實例,初始化了三維數(shù)組,并使用三維索引器來訪問和設(shè)置數(shù)組中的元素。
請注意,三維數(shù)組的索引器需要檢查每個維度的索引是否在數(shù)組的邊界內(nèi)。我們使用 GetLength 方法來獲取每個維度的大小,并在索引超出范圍時拋出 IndexOutOfRangeException 異常。
上面的代碼定義了一個名為 MyClass 的類,它包含了一個三維整數(shù)數(shù)組作為其屬性,并為這個數(shù)組提供了一個三維索引器。下面是對代碼的詳細解釋:
- 三維數(shù)組的聲明:
private int[,,] _items; // 三維整數(shù)數(shù)組
這里聲明了一個名為 _items 的三維整數(shù)數(shù)組。在C#中,三維數(shù)組使用2個逗號來分隔維度。
- 三維索引器的定義:
public int this[int index1, int index2, int index3]
{
// ...
}
索引器使用 this 關(guān)鍵字定義,它允許我們使用類似數(shù)組的語法來訪問類的實例。在這個例子中,索引器接受三個參數(shù):index1、index2 和 index3,分別對應(yīng)三維數(shù)組的三個維度。
-
索引器的
get訪問器:
get
{
// ...
}
get 訪問器用于從數(shù)組中檢索值。首先,它檢查提供的索引是否在數(shù)組的邊界內(nèi)。這是通過調(diào)用 GetLength 方法并傳遞相應(yīng)的維度索引來完成的。如果索引有效,它返回數(shù)組中指定位置的值。如果索引無效,它拋出 IndexOutOfRangeException 異常。
-
索引器的
set訪問器:
set
{
// ...
}
set 訪問器用于在數(shù)組的指定位置設(shè)置值。與 get 訪問器類似,它也檢查索引的有效性。如果索引有效,它將值賦給數(shù)組的指定位置。如果索引無效,同樣拋出 IndexOutOfRangeException 異常。
- 初始化三維數(shù)組的方法:
public void InitializeArray(int size1, int size2, int size3)
{
_items = new int[size1, size2, size3];
// 初始化數(shù)組或執(zhí)行其他操作
}
這個方法用于初始化三維數(shù)組。它接受三個參數(shù),分別代表數(shù)組在每個維度上的大小,并創(chuàng)建一個新的三維數(shù)組。您可以在這個方法中添加額外的邏輯來初始化數(shù)組的值或執(zhí)行其他操作。
-
在
Main方法中使用索引器:
MyClass myClass = new MyClass();
myClass.InitializeArray(3, 3, 3); // 初始化一個3x3x3的三維數(shù)組
// 使用三維索引器訪問和設(shè)置元素
在 Main 方法中,我們創(chuàng)建了 MyClass 的一個實例,并調(diào)用 InitializeArray 方法來初始化三維數(shù)組。然后,我們使用三維索引器來訪問和設(shè)置數(shù)組中的元素,就像操作普通數(shù)組一樣。
這個例子展示了如何在C#中為三維數(shù)組創(chuàng)建索引器,并提供了一種直觀的方式來訪問和修改數(shù)組的元素。
定義了一個名為 Person 的類,其中包含了三個字符數(shù)組字段:_show、_info 和 _music。類中定義了兩個索引器,一個是基本的一維索引器,另一個是重載后的索引器,它接受一個字符串參數(shù) type 和一個整數(shù)索引 index。
class Person
{
// 字段:數(shù)組一
private char[] _show = { '就', '是', '有', '這', '種', '操', '作', '!' };
// 字段:數(shù)組二
private char[] _info = { '我', '是', '練', '習(xí)', '時', '長', '兩', '年', '半', '的', '偶', '像', '練', '習(xí)', '生' };
// 字段:數(shù)組三
private char[] _music = { '音', '樂', '響', '起', '!', '雞', '你', '太', '美' };
// 基本索引器
public char this[int index]
{
get
{
if (index >= 0 && index < _show.Length)
{
return _show[index];
}
else
{
Console.WriteLine("取值的索引超出范圍");
return '\0';
}
}
set
{
if (index >= 0 && index < _show.Length)
{
_show[index] = value;
}
else
{
Console.WriteLine("賦值的索引超出范圍");
}
}
}
// 重載索引器
public char this[string type, int index]
{
get
{
char result = '\0';
switch (type)
{
case "數(shù)組一":
if (index >= 0 && index < _show.Length)
{
return _show[index];
}
break;
case "數(shù)組二":
if (index >= 0 && index < _info.Length)
{
return _info[index];
}
break;
case "數(shù)組三":
if (index >= 0 && index < _music.Length)
{
return _music[index];
}
break;
default:
Console.WriteLine("不在數(shù)組范圍!請輸入:數(shù)組一/數(shù)組二/數(shù)組三");
break;
}
return result;
}
set
{
switch (type)
{
case "數(shù)組一":
if (index >= 0 && index < _show.Length)
{
_show[index] = value;
}
else
{
Console.WriteLine("賦值的索引超出范圍");
}
break;
// 為數(shù)組二和數(shù)組三添加類似的邏輯
default:
Console.WriteLine("不在數(shù)組范圍!請輸入:數(shù)組一/數(shù)組二/數(shù)組三");
break;
}
}
}
}
基本索引器:
這個索引器允許您通過整數(shù)索引來訪問和設(shè)置_show數(shù)組中的字符。如果索引超出了_show數(shù)組的范圍,它會提示用戶索引超出范圍,并返回一個空字符'\0'。重載索引器:
這個索引器允許您通過指定的數(shù)組類型("數(shù)組一"、"數(shù)組二" 或 "數(shù)組三")和整數(shù)索引來訪問和設(shè)置對應(yīng)的數(shù)組。它使用switch語句來判斷用戶輸入的type,并根據(jù)type返回對應(yīng)的數(shù)組中的字符。如果索引超出了指定數(shù)組的范圍,它會提示用戶重新輸入。
以下是對重載索引器的一些改進和解釋:
- 在
get訪問器中,如果type不匹配任何已知的數(shù)組類型,應(yīng)該返回一個默認值(例如'\0'),而不是result,因為result被初始化為'\0'。 - 在
set訪問器中,您可能也想添加類似的邏輯,以允許用戶通過重載的索引器設(shè)置數(shù)組的值。 - 在
set訪問器中,您應(yīng)該在所有情況下返回void,因為您正在設(shè)置值而不是返回值。 - 為重載索引器的
set訪問器添加了與get訪問器相似的邏輯。這樣,用戶就可以通過指定數(shù)組類型和索引來設(shè)置數(shù)組中的值了。如果索引超出范圍,它會提示用戶索引超出范圍。
索引器的重載:
public char this[string type, int index]
{
get
{
// ...(索引器的代碼)
}
set
{
// ...(索引器的代碼)
}
}
這段代碼定義了一個名為 this 的索引器,它是 Person 類的一部分。這個索引器是重載的,意味著它有兩個參數(shù):一個字符串 type 和一個整數(shù) index。索引器允許您使用類似于數(shù)組的語法來訪問和設(shè)置類的內(nèi)部數(shù)組的元素。
get訪問器:當(dāng)您嘗試從索引器獲取值時(例如person["數(shù)組一", 0]),get訪問器會被調(diào)用。它根據(jù)傳入的type參數(shù)確定要訪問哪個數(shù)組,然后使用index參數(shù)來獲取數(shù)組中特定位置的元素。set訪問器:當(dāng)您嘗試設(shè)置索引器的值時(例如person["數(shù)組一", 0] = 'A'),set訪問器會被調(diào)用。它同樣根據(jù)type參數(shù)確定要操作哪個數(shù)組,并將新的值設(shè)置到指定的index位置。
<u>這里是 get 和 set 訪問器的內(nèi)部邏輯的簡化版本:</u>
public char this[string type, int index]
{
get
{
// 根據(jù)type參數(shù)選擇正確的數(shù)組
char[] selectedArray;
switch (type)
{
case "數(shù)組一":
selectedArray = _show;
break;
case "數(shù)組二":
selectedArray = _info;
break;
case "數(shù)組三":
selectedArray = _music;
break;
default:
Console.WriteLine("無效的數(shù)組類型。");
return '\0'; // 返回一個空字符
}
// 檢查索引是否在數(shù)組的有效范圍內(nèi)
if (index >= 0 && index < selectedArray.Length)
{
return selectedArray[index];
}
else
{
Console.WriteLine("索引超出范圍。");
return '\0'; // 返回一個空字符
}
}
set
{
// 根據(jù)type參數(shù)選擇正確的數(shù)組
char[] selectedArray;
switch (type)
{
case "數(shù)組一":
selectedArray = _show;
break;
case "數(shù)組二":
selectedArray = _info;
break;
case "數(shù)組三":
selectedArray = _music;
break;
default:
Console.WriteLine("無效的數(shù)組類型。");
return;
}
// 檢查索引是否在數(shù)組的有效范圍內(nèi)
if (index >= 0 && index < selectedArray.Length)
{
selectedArray[index] = value;
}
else
{
Console.WriteLine("索引超出范圍。");
}
}
}
在這個簡化的例子中,get 和 set 訪問器都使用 switch 語句來確定要操作的數(shù)組。然后,它們檢查索引是否在數(shù)組的有效范圍內(nèi)。如果是,get 訪問器返回數(shù)組中指定索引的元素,而 set 訪問器將新值設(shè)置到指定索引。如果索引無效,它們會在控制臺輸出錯誤消息。
在 Main 方法中,您可以通過傳遞數(shù)組類型和索引來調(diào)用這個索引器,例如:
Person person = new Person();
Console.WriteLine(person["數(shù)組一", 0]); // 輸出數(shù)組一的第一個元素
person["數(shù)組一", 0] = 'A'; // 將數(shù)組一的第一個元素設(shè)置為 'A'
這樣,您就可以通過索引器來訪問和修改 Person 類中定義的數(shù)組了。
<u>public char this[string type, int index]</u> 這部分代碼定義了一個索引器,它不是固定必須這樣寫,但它遵循了C#中索引器的語法規(guī)則。索引器的語法允許您定義一個類似于數(shù)組的索引訪問模式,但您可以根據(jù)需要自定義參數(shù)和返回類型。
在這個特定的例子中:
-
public是訪問修飾符,表示這個索引器可以在類的外部被訪問。 -
char是返回類型,表示這個索引器返回一個字符(char類型)。 -
this是索引器的關(guān)鍵字,它在這里用作方法名,表示這是一個索引器。 -
[string type, int index]是索引器的參數(shù)列表,其中type是一個字符串參數(shù),用于指定要訪問的數(shù)組類型;index是一個整數(shù)參數(shù),用于指定數(shù)組中的索引位置。
您可以選擇不同的參數(shù)類型和數(shù)量來滿足您的具體需求。例如,如果您的類中只有一個數(shù)組,或者您希望索引器只接受一個參數(shù),您可以簡化索引器的定義。但在這個例子中,由于有三個不同的數(shù)組,所以需要一個額外的參數(shù)來區(qū)分它們。
如果您不希望使用字符串來指定數(shù)組類型,您也可以定義三個不同的索引器,每個索引器對應(yīng)一個數(shù)組,如下所示:
public char this[int index] // 用于數(shù)組一
{
get { /* ... */ }
set { /* ... */ }
}
public char this[string type, int index] // 用于數(shù)組二和數(shù)組三
{
get { /* ... */ }
set { /* ... */ }
}
在這個例子中,我們?yōu)槊總€數(shù)組定義了一個單獨的索引器。這樣,您可以根據(jù)數(shù)組的類型直接調(diào)用相應(yīng)的索引器,而不需要傳遞額外的類型參數(shù)。
總之,索引器的寫法不是固定的,您可以根據(jù)實際情況和需求來設(shè)計索引器的簽名。
下面是一個例子,展示了如何為一個包含多個不同類型屬性的類定義兩個不同類型的索引器重載。假設(shè)我們有一個名為 Bookshelf 的類,它用來表示書架,書架上可以放不同類型的書籍(例如小說、教科書和雜志)。我們想要通過索引器來訪問特定類型的書籍。
using System;
public class Bookshelf
{
// 字段:存儲不同類型的書籍
private List<Book> novels;
private List<教科書> textbooks;
private List<Magazine> magazines;
// 構(gòu)造函數(shù),初始化書籍列表
public Bookshelf()
{
novels = new List<Book>();
textbooks = new List<教科書>();
magazines = new List<Magazine>();
}
// 索引器重載1:用于訪問小說
public Book this[int index, BookType type]
{
get
{
if (type == BookType.Novel)
{
if (index >= 0 && index < novels.Count)
{
return novels[index];
}
}
else
{
throw new ArgumentException("Invalid book type for this indexer.");
}
}
set
{
if (type == BookType.Novel)
{
if (index >= 0 && index < novels.Count)
{
novels[index] = value;
}
else
{
throw new IndexOutOfRangeException("Index out of range.");
}
}
else
{
throw new ArgumentException("Invalid book type for this indexer.");
}
}
}
// 索引器重載2:用于訪問教科書和雜志
public Book this[int index, BookType type]
{
get
{
switch (type)
{
case BookType.Textbook:
if (index >= 0 && index < textbooks.Count)
{
return textbooks[index];
}
break;
case BookType.Magazine:
if (index >= 0 && index < magazines.Count)
{
return magazines[index];
}
break;
default:
throw new ArgumentException("Invalid book type for this indexer.");
}
}
set
{
switch (type)
{
case BookType.Textbook:
if (index >= 0 && index < textbooks.Count)
{
textbooks[index] = (教科書) value;
}
else
{
throw new IndexOutOfRangeException("Index out of range.");
}
break;
case BookType.Magazine:
if (index >= 0 && index < magazines.Count)
{
magazines[index] = (Magazine) value;
}
else
{
throw new IndexOutOfRangeException("Index out of range.");
}
break;
default:
throw new ArgumentException("Invalid book type for this indexer.");
}
}
}
}
// 假設(shè)這些是書籍的不同類型
public class Book { }
public class 教科書 : Book { }
public class Magazine : Book { }
// 枚舉,表示書籍的類型
public enum BookType
{
Novel,
Tutorial,
Magazine
}
class Program
{
static void Main(string[] args)
{
Bookshelf shelf = new Bookshelf();
// 添加一些書籍到書架
shelf.novels.Add(new Book());
shelf.textbooks.Add(new 教科書());
shelf.magazines.Add(new Magazine());
// 使用索引器訪問和設(shè)置小說
Book novel = shelf[0, BookType.Novel];
shelf[0, BookType.Novel] = new Book();
// 使用索引器訪問和設(shè)置教科書
教科書 textbook = shelf[0, BookType.Tutorial];
shelf[0, BookType.Tutorial] = new 教科書();
// 使用索引器訪問和設(shè)置雜志
Magazine magazine = shelf[0, BookType.Magazine];
shelf[0, BookType.Magazine] = new Magazine();
}
}
在這個例子中,我們定義了兩個索引器重載:
- 第一個索引器
this[int index, BookType type]專門用于訪問和設(shè)置小說(Book類型)。 - 第二個索引器
this[int index, BookType type]用于訪問和設(shè)置教科書(教科書類型)和雜志(Magazine類型)。這里我們使用了switch語句來根據(jù)書籍類型選擇正確的列表。
我們還定義了一個 BookType 枚舉,用于表示書籍的類型。這樣,當(dāng)我們使用索引器時,可以通過傳遞 BookType 枚舉值來指定要訪問的書籍類型。
請注意,這個例子中的索引器重載可能會導(dǎo)致一些混淆,因為它們有相同的簽名。在實際應(yīng)用中,為了避免這種情況,您可能需要為每個索引器重載定義不同的參數(shù)列表。例如,您可以為每種書籍類型定義一個單獨的索引器,或者使用不同的方法名。
索引器(Indexer)在C#中通常用于以下幾種場景:
模擬數(shù)組或集合的訪問:
當(dāng)您想要提供一個類,使其行為類似于數(shù)組或集合,允許用戶通過索引來訪問或修改元素時,索引器非常有用。例如,自定義集合類、列表或字典。封裝數(shù)據(jù)結(jié)構(gòu):
如果您的類封裝了一個復(fù)雜的數(shù)據(jù)結(jié)構(gòu)(如二維數(shù)組、鏈表、樹等),索引器可以提供一個簡單的接口來訪問這些數(shù)據(jù)結(jié)構(gòu)中的元素。數(shù)據(jù)庫操作:
在與數(shù)據(jù)庫交互時,索引器可以用來模擬數(shù)據(jù)庫表的行和列。例如,您可以創(chuàng)建一個類來表示數(shù)據(jù)庫中的表,索引器可以用于訪問特定行和列的數(shù)據(jù)。文件系統(tǒng)操作:
在處理文件系統(tǒng)時,索引器可以用來訪問文件或目錄列表。例如,一個類可以表示一個目錄,索引器可以用于獲取目錄中的文件或子目錄。游戲開發(fā):
在游戲開發(fā)中,索引器可以用來訪問游戲?qū)ο蟮募?,如角色、敵人、子彈等。這使得代碼更易于理解和維護。數(shù)據(jù)綁定:
在用戶界面編程中,索引器常用于實現(xiàn)數(shù)據(jù)綁定。例如,當(dāng)您需要將一個列表綁定到用戶界面的某個部分時,索引器可以簡化數(shù)據(jù)的訪問。簡化API:
索引器可以提供一個簡潔的API,使得外部代碼可以通過索引來操作類的狀態(tài),而不需要暴露內(nèi)部的實現(xiàn)細節(jié)。多維數(shù)據(jù)結(jié)構(gòu):
對于多維數(shù)據(jù)結(jié)構(gòu),如三維數(shù)組或自定義的多維集合,索引器可以提供一種直觀的方式來訪問特定維度的元素。
使用索引器時,您應(yīng)該考慮其性能影響。索引器在每次訪問時都會執(zhí)行額外的代碼,這可能會影響性能。因此,在性能敏感的應(yīng)用中,您可能需要權(quán)衡索引器的便利性和性能開銷。
索引器通常在以下情況下需要重載:
支持多種數(shù)據(jù)類型:
當(dāng)您需要一個索引器來處理不同類型的數(shù)據(jù)時,您可能需要重載索引器。例如,如果您的類管理了多種類型的對象(如字符串、整數(shù)、自定義對象等),您可能需要為每種類型提供一個專門的索引器。不同的訪問模式:
如果您的類需要支持不同的訪問模式,例如,一個索引器用于只讀訪問,另一個用于讀寫訪問,您可能需要重載索引器以提供不同的行為。不同的參數(shù)數(shù)量或類型:
當(dāng)您需要根據(jù)不同的參數(shù)數(shù)量或類型來訪問數(shù)據(jù)時,索引器重載是必要的。例如,一個索引器可能接受一個整數(shù)索引來訪問一維數(shù)組,而另一個可能接受兩個整數(shù)索引來訪問二維數(shù)組。不同的數(shù)據(jù)結(jié)構(gòu):
如果您的類封裝了不同的數(shù)據(jù)結(jié)構(gòu)(如列表、字典、集合等),您可能需要為每種數(shù)據(jù)結(jié)構(gòu)提供一個專門的索引器。提供更靈活的接口:
為了提供更靈活的接口,您可能需要重載索引器以支持不同的參數(shù)組合。例如,一個索引器可能接受一個字符串和一個整數(shù)來訪問字典中的鍵值對,而另一個可能只接受一個字符串來訪問特定的屬性。遵循特定的設(shè)計模式:
在某些設(shè)計模式中,如外觀模式(Facade Pattern),您可能需要重載索引器來提供一個統(tǒng)一的接口來訪問底層系統(tǒng)的多個組件。滿足特定的業(yè)務(wù)邏輯:
如果業(yè)務(wù)邏輯要求根據(jù)不同的條件來返回不同的數(shù)據(jù),您可能需要重載索引器來實現(xiàn)這些條件邏輯。
在設(shè)計索引器重載時,您應(yīng)該確保重載的索引器之間有明確的區(qū)分,以避免混淆。同時,您應(yīng)該考慮索引器的使用場景和性能影響,確保索引器的使用不會對性能產(chǎn)生負面影響。如果可能,最好通過方法重載或?qū)傩詠泶嫠饕髦剌d,以保持代碼的清晰和簡潔。
索引器的鏈式調(diào)用:
namespace 索引器的理解
{
class Student
{
//我是三好學(xué)生
private char[] _info = null;
public Student(char[] info)
{
this._info = info;
}
//構(gòu)建索引器
public char this[int index]
{
get
{
if (_info != null)
{
if (index >= 0 && index <= _info.Length)
{
return this._info[index];
}
else
{
//提示不在數(shù)組的范圍
Console.WriteLine("不在數(shù)組的索引范圍[{0},{1}],請重新輸入!", 0, _info.Length);
return '\0';
}
}
else
{
return '\0';
}
}
set
{
if (_info != null)
{
if (index >= 0 && index <= _info.Length)
{
_info[index] = value;
}
else
{
//提示不在范圍
Console.WriteLine("不在數(shù)組的索引范圍[{0},{1}],請重新輸入!", 0, _info.Length);
}
}
else
{
//提示不在范圍
Console.WriteLine("不在數(shù)組的索引范圍[{0},{1}],請重新輸入!", 0, _info.Length);
}
}
}
}
class School
{
//字段:數(shù)組四
private Student[] _student =
{
new Student(new char[] { '蔡', '徐', '坤' }),
new Student(new char[] { '洪', '世', '賢' }),
new Student(new char[] { '斷', '水', '流','大','師','兄' }),
};
public Student this[int index]
{
get
{
if (index >= 0 && index < _student.Length)
{
return _student[index];
}
else
{
//提示不在數(shù)組的索引范圍請重新輸入
Console.WriteLine("不在數(shù)組的索引范圍[{0},{1}],請重新輸入!", 0, _student.Length);
return null;
}
}
set
{
if (index >= 0 && index < _student.Length)
{
_student[index] = value;
}
else
{
//提示不在數(shù)組的索引范圍請重新輸入
Console.WriteLine("不在數(shù)組的索引范圍[{0},{1}],請重新輸入!", 0, _student.Length);
}
}
}
}
internal class Program
{
static void Main(string[] args)
{
//打印對象數(shù)組當(dāng)中的內(nèi)容
School school = new School();
Console.Write(school[0][0]);
Console.Write(school[0][1]);
Console.Write(school[0][2]);
Console.WriteLine();
Console.Write(school[1][0]);
Console.Write(school[1][1]);
Console.Write(school[1][2]);
Console.WriteLine();
Console.Write(school[2][0]);
Console.Write(school[2][1]);
Console.Write(school[2][2]);
Console.Write(school[2][3]);
Console.Write(school[2][4]);
Console.Write(school[2][5]);
Console.ReadKey();
}
}
}
這段代碼定義了兩個類:Student 和 School,以及一個 Program 類,它包含了程序的入口點 Main 方法。下面是對這段代碼的詳細解釋:
- Student 類:
-
_info字段是一個字符數(shù)組,用于存儲學(xué)生的姓名信息。 -
Student類的構(gòu)造函數(shù)接受一個字符數(shù)組作為參數(shù),并將其賦值給_info字段。 - 類還定義了一個索引器,允許通過索引訪問和設(shè)置
_info字段中的單個字符。索引器的get和set訪問器都包含了邊界檢查,以確保索引值在有效范圍內(nèi)。如果索引超出范圍,會在控制臺輸出錯誤消息,并返回一個空字符'\0'(在get訪問器中)或不執(zhí)行任何操作(在set訪問器中)。
- School 類:
-
_student字段是一個Student對象數(shù)組,每個對象代表一個學(xué)生。 - 類同樣定義了一個索引器,允許通過索引訪問和設(shè)置
_student數(shù)組中的Student對象。這個索引器也包含了邊界檢查,如果索引超出范圍,會在控制臺輸出錯誤消息,并返回null(在get訪問器中)或不執(zhí)行任何操作(在set訪問器中)。
- Program 類:
-
Main方法是程序的入口點。 - 創(chuàng)建了一個
School類的實例school。 - 使用索引器訪問
school數(shù)組中的每個學(xué)生,并打印出學(xué)生的姓名。由于Student類的索引器允許訪問_info字段中的字符,這里實際上是在打印每個學(xué)生的姓名的每個字符。
在 Main 方法中,程序嘗試打印出每個學(xué)生的姓名。例如,school[0][0] 會打印出第一個學(xué)生姓名的第一個字符('蔡'),school[0][1] 會打印出第二個字符('徐'),依此類推。對于第三個學(xué)生,由于其姓名有六個字符,所以 school[2][5] 會打印出第六個字符('兄')。
這段代碼演示了如何在類中使用索引器來模擬數(shù)組的索引訪問,并提供了一種方式來處理索引超出范圍的情況。同時,它也展示了如何在類的實例之間共享數(shù)據(jù)(在這個例子中是學(xué)生姓名)并對其進行操作。
打印學(xué)生名字的代碼:
School school = new School();
Console.Write(school[0][0]);
Console.Write(school[0][1]);
// ...
這段代碼創(chuàng)建了一個 School 對象 school,然后通過索引器訪問每個學(xué)生的名字的每個字符,并將其打印到控制臺。例如,school[0][0] 訪問第一個學(xué)生的名字的第一個字符。
school[0][0] 這樣的表達式能夠正常工作,是因為在 School 類和 Student 類中都定義了索引器。這里的索引器允許您通過方括號 [] 的語法來訪問對象的屬性或字段。這種語法通常用于數(shù)組或集合類型,但也可以用于任何定義了索引器的類。
讓我們逐步分解 school[0][0] 這個表達式:
-
school是School類的一個實例。 -
school[0]是對School類索引器的調(diào)用,它使用索引0來獲取_student數(shù)組中的第一個Student對象。這個索引器返回的是Student類型的對象。 -
school[0][0]中的第二個索引器調(diào)用實際上是對Student類索引器的調(diào)用。由于Student類的索引器接受一個整數(shù)索引,它嘗試獲取Student對象的_info字段中的第一個字符(索引為0)。
這種嵌套的索引器調(diào)用是可能的,因為 School 類的索引器返回了一個 Student 對象,而 Student 類也定義了自己的索引器。當(dāng)您對 School 類的索引器返回的對象進行索引時,實際上是在調(diào)用那個對象的索引器。
這里是一個簡化的例子來說明這個過程:
// School 類的索引器
public Student this[int index]
{
get { return _student[index]; }
}
// Student 類的索引器
public char this[int index]
{
get { return _info[index]; }
}
當(dāng)您執(zhí)行 school[0][0] 時:
-
school[0]返回_student數(shù)組的第一個Student對象。 -
school[0][0]實際上是(school[0])[0],即對第一個Student對象調(diào)用索引器,獲取其_info字段的第一個字符。
這種索引器的鏈式調(diào)用在C#中是允許的,只要每個類都正確地定義了索引器,并且返回的類型支持進一步的索引訪問。
讓我們通過一個簡單的例子來理解索引器的鏈式調(diào)用。假設(shè)我們有一個表示二維網(wǎng)格的類,這個類有兩個索引器:一個用于訪問網(wǎng)格的行(二維數(shù)組的一維表示),另一個用于訪問行中的元素(二維數(shù)組的二維表示)。
首先,我們定義一個 Grid 類來表示這個二維網(wǎng)格:
public class Grid
{
// 字段:二維整數(shù)數(shù)組
private int[,] grid = new int[3, 3];
// 索引器:用于訪問網(wǎng)格的行
public int[] this[int rowIndex]
{
get
{
// 返回指定行的數(shù)組
return new int[] { grid[rowIndex, 0], grid[rowIndex, 1], grid[rowIndex, 2] };
}
set
{
// 設(shè)置指定行的元素
grid[rowIndex, 0] = value[0];
grid[rowIndex, 1] = value[1];
grid[rowIndex, 2] = value[2];
}
}
// 索引器:用于訪問網(wǎng)格中的單個元素
public int this[int rowIndex, int columnIndex]
{
get
{
// 返回指定行和列的元素
return grid[rowIndex, columnIndex];
}
set
{
// 設(shè)置指定行和列的元素
grid[rowIndex, columnIndex] = value;
}
}
}
在這個 Grid 類中,我們有兩個索引器:
第一個索引器接受一個整數(shù)
rowIndex作為參數(shù),用于獲取或設(shè)置網(wǎng)格的某一行。這個索引器返回一個整數(shù)數(shù)組,代表了網(wǎng)格的一行。第二個索引器接受兩個整數(shù)參數(shù)
rowIndex和columnIndex,用于直接獲取或設(shè)置網(wǎng)格中特定行和列的元素。
現(xiàn)在,我們可以創(chuàng)建一個 Grid 類的實例,并使用鏈式索引器來訪問和設(shè)置網(wǎng)格的元素:
class Program
{
static void Main(string[] args)
{
Grid myGrid = new Grid();
// 使用鏈式索引器設(shè)置第一行的元素
myGrid[0] = new int[] { 1, 2, 3 };
// 使用鏈式索引器設(shè)置第二行,第三列的元素
myGrid[1, 2] = 4;
// 使用鏈式索引器獲取并打印第二行的內(nèi)容
int[] row = myGrid[1];
foreach (int value in row)
{
Console.Write(value + " ");
}
Console.WriteLine();
}
}
在這個例子中,我們首先創(chuàng)建了一個 Grid 類的實例 myGrid。然后,我們使用鏈式索引器來設(shè)置網(wǎng)格的第一行和第二行第三列的值。接著,我們使用第二個索引器來獲取第二行的內(nèi)容,并將其打印出來。
這個例子展示了如何通過索引器的鏈式調(diào)用來操作一個類的不同層級的屬性。這種模式在處理復(fù)雜的數(shù)據(jù)結(jié)構(gòu)時非常有用,尤其是當(dāng)你需要提供一個直觀的方式來訪問嵌套的數(shù)據(jù)時。