C# 索引器和委托全面解析(十二)
- 编程语言
- 2天前
- 5热度
- 0评论
在 C# 编程中,索引器和委托是非常重要的特性,它们能够让你的代码更加灵活和高效。本文将详细介绍索引器和委托的基本概念、语法、应用场景以及一些高级用法,帮助你更好地理解和使用这些强大的工具。
索引器(Indexer)简介
什么是索引器?
索引器允许你像访问数组一样访问类的成员。通过索引器,你可以使用数组访问运算符 [] 来获取或设置类的成员。这使得类的行为类似于一个“虚拟数组”。
索引器的用途
索引器的行为类似于属性,但它们没有名称,而是使用 this 关键字来指向对象实例。索引器主要用于将类的实例数据分成更小的部分,并索引每个部分,从而实现更灵活的数据访问。
一维索引器的语法
public element-type this[int index]
{
get { /* 获取值的逻辑 */ }
set { /* 设置值的逻辑 */ }
}示例:基本索引器
假设我们有一个类 IndexedNames,它包含一个字符串数组 namelist。我们可以为这个类定义一个索引器,以便通过索引访问数组中的元素。
using System;
namespace IndexerApplication
{
class IndexedNames
{
private string[] namelist = new string[size];
public static int size = 10;
public IndexedNames()
{
for (int i = 0; i < size; i++)
{
namelist[i] = "N. A.";
}
}
public string this[int index]
{
get
{
if (index >= 0 && index <= size - 1)
{
return namelist[index];
}
else
{
return "";
}
}
set
{
if (index >= 0 && index <= size - 1)
{
namelist[index] = value;
}
}
}
static void Main(string[] args)
{
IndexedNames names = new IndexedNames();
names[0] = "Zara";
names[1] = "Riz";
names[2] = "Nuha";
names[3] = "Asif";
names[4] = "Davinder";
names[5] = "Sunil";
names[6] = "Rubic";
for (int i = 0; i < IndexedNames.size; i++)
{
Console.WriteLine(names[i]);
}
Console.ReadKey();
}
}
}重载索引器
索引器可以被重载,以支持多个参数或不同类型的参数。例如,我们可以为 IndexedNames 类添加一个基于字符串的索引器,用于查找特定名字的索引。
public int this[string name]
{
get
{
for (int index = 0; index < size; index++)
{
if (namelist[index] == name)
{
return index;
}
}
return -1;
}
}示例:重载索引器
using System;
namespace IndexerApplication
{
class IndexedNames
{
private string[] namelist = new string[size];
public static int size = 10;
public IndexedNames()
{
for (int i = 0; i < size; i++)
{
namelist[i] = "N. A.";
}
}
public string this[int index]
{
get
{
if (index >= 0 && index <= size - 1)
{
return namelist[index];
}
else
{
return "";
}
}
set
{
if (index >= 0 && index <= size - 1)
{
namelist[index] = value;
}
}
}
public int this[string name]
{
get
{
for (int index = 0; index < size; index++)
{
if (namelist[index] == name)
{
return index;
}
}
return -1;
}
}
static void Main(string[] args)
{
IndexedNames names = new IndexedNames();
names[0] = "Zara";
names[1] = "Riz";
names[2] = "Nuha";
names[3] = "Asif";
names[4] = "Davinder";
names[5] = "Sunil";
names[6] = "Rubic";
for (int i = 0; i < IndexedNames.size; i++)
{
Console.WriteLine(names[i]);
}
Console.WriteLine(names["Nuha"]);
Console.ReadKey();
}
}
}委托(Delegate)简介
什么是委托?
委托是一种类型安全的函数指针,它可以存储对某个方法的引用。委托允许你在运行时动态地调用方法,常用于事件处理、回调函数等场景。
委托的用途
委托的主要用途包括:
- 事件处理:用于响应用户界面中的事件。
- 回调函数:在异步编程中,用于在操作完成后调用某个方法。
- 多播:允许多个方法被同一个委托调用。
声明委托
委托的声明类似于方法的声明,但它不需要实现方法体。以下是声明委托的基本语法:
public delegate 返回类型 委托名(参数类型 参数名, ...);示例:声明委托
public delegate int MathOperation(int x, int y);实例化委托
一旦声明了委托类型,就可以使用 new 关键字创建委托实例,并将其与具体的方法关联起来。
MathOperation add = new MathOperation(AddNumbers);示例:实例化和使用委托
using System;
namespace DelegateAppl
{
delegate int NumberChanger(int n);
class TestDelegate
{
static int num = 10;
public static int AddNum(int p)
{
num += p;
return num;
}
public static int MultNum(int q)
{
num *= q;
return num;
}
public static int GetNum()
{
return num;
}
static void Main(string[] args)
{
NumberChanger nc1 = new NumberChanger(AddNum);
NumberChanger nc2 = new NumberChanger(MultNum);
nc1(25);
Console.WriteLine("Value of Num: {0}", GetNum());
nc2(5);
Console.WriteLine("Value of Num: {0}", GetNum());
Console.ReadKey();
}
}
}委托的多播
委托对象可以使用 + 运算符进行合并,形成一个多播委托。多播委托在调用时会依次调用其包含的所有方法。
示例:委托的多播
using System;
namespace DelegateAppl
{
delegate int NumberChanger(int n);
class TestDelegate
{
static int num = 10;
public static int AddNum(int p)
{
num += p;
return num;
}
public static int MultNum(int q)
{
num *= q;
return num;
}
public static int GetNum()
{
return num;
}
static void Main(string[] args)
{
NumberChanger nc1 = new NumberChanger(AddNum);
NumberChanger nc2 = new NumberChanger(MultNum);
NumberChanger nc = nc1 + nc2;
nc(5);
Console.WriteLine("Value of Num: {0}", GetNum());
Console.ReadKey();
}
}
}移除委托
你可以使用 - 运算符从多播委托中移除某个方法。
示例:移除委托
using System;
public class Program
{
public delegate void PrintMessage(string message);
public static void PrintUpperCase(string message)
{
Console.WriteLine(message.ToUpper());
}
public static void PrintLowerCase(string message)
{
Console.WriteLine(message.ToLower());
}
public static void Main()
{
PrintMessage print = PrintUpperCase;
print += PrintLowerCase;
// 移除 PrintLowerCase 方法
print -= PrintLowerCase;
// 调用委托(只会调用 PrintUpperCase)
print("Hello, C#"); // 输出: HELLO, C#
}
}委托和事件
委托经常与事件一起使用。事件是一种特殊的委托,用于实现发布-订阅模式。事件通常用于响应用户界面中的操作。
示例:委托和事件
using System;
public class Button
{
// 定义一个事件
public event EventHandler Click;
// 引发事件的方法
public void OnClick()
{
Click?.Invoke(this, EventArgs.Empty);
}
}
public class Program
{
public static void Main()
{
Button button = new Button();
// 订阅事件
button.Click += Button_Click;
// 引发事件
button.OnClick(); // 输出 "Button clicked!"
}
private static void Button_Click(object sender, EventArgs e)
{
Console.WriteLine("Button clicked!");
}
}常见的委托类型
C# 提供了一些常用的委托类型,这些委托类型可以简化你的代码。
1. Action
Action 代表不返回值的方法。它可以接受最多 16 个参数。
Action
<string> printMessage = Console.WriteLine;
printMessage("Hello");2. Func
Func 代表有返回值的方法。它可以接受最多 16 个参数,其中最后一个参数是返回值类型。
Func<int, int, int> add = (x, y) => x + y;
Console.WriteLine(add(3, 4)); // 输出: 7总结
通过本文,我们详细介绍了 C# 中的索引器和委托,包括它们的基本概念、语法、应用场景以及一些高级用法。希望这些内容能帮助你更好地理解和使用这些强大的工具,提升你的编程技能。如果你有任何疑问或建议,欢迎在评论区留言交流。