目录
泛型事件:使用泛型委托(如EventHandler)来声明事件,可以传递更具体的事件数据。
一.结构体
定义:
struct关键字用于声明一个值类型.结构体适合表示轻量级对象,如坐标,复杂数等
特点:
- 值类型:数据存储在栈(Stack)上,变量直接包含数据值
- 不可继承:结构体不支持继承(无法被继承,也不能继承自其他类型,除了实现接口)
- 默认不可为空:值类型变量默认情况下不能为null(除非使用Nullable<T>)
- 内存效率:在栈上分配和释放,效率较高,适合小型数据结构
用法:
- 不适合过大的数据结构,否则会影响性能
- 结构体应设计为不可变(Immutability),即成员应尽量设为只读
代码示例:
public struct Point
{
public double X { get; }
public double Y { get; }
public Point(double x, double y)
{
X = x;
Y = y;
}
}
二.特殊的结构体(ref struct):
定义:
- ref struct是一种特殊的结构体,限制其只能在栈上分配,不能在堆上分配
特点:
- 仅限栈分配:ref struct实例不能被分配到托管堆上,保证了高性能的内存访问
- 无法装箱:不能转换为object类型,不能使用如泛型,接口等需要装箱的特性
- 用途限定:常用于需要高性能和低延迟的场景,例如Span<T>,ReadonlySpan<T>等类型
限制:
- 不能捕获到异步方法,迭代器或Lambda表达式中:因为这些场景中可能导致变量逃逸出栈
- 不能赋值给类型为
object
的变量 - 不能实现接口
代码示例:
public ref struct SpanWrapper
{
private Span<byte> _buffer;
public SpanWrapper(Span<byte> buffer)
{
_buffer = buffer;
}
// 成员方法和属性
}
三.枚举
定义:enum关键字用于声明一个枚举类型,由命名常量的集合组成
特点:
- 值类型:枚举的底层类型是整型(默认是int),每个枚举成员都有一个关联的整数值
- 提高可读性:使用有意义的名称代替数字,提高代码的可读性和可维护性
- 可指定底层类型:可以显式指定底层类型,例如byte,short等
- 位标志(Flags):使用
[Flags]
属性可以让枚举表示位域,支持按位操作
代码示例:
public enum DaysOfWeek : byte
{
Sunday = 0,
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 6
}
// 使用枚举
DaysOfWeek today = DaysOfWeek.Monday;
位标志代码示例:
[Flags]
public enum FileAccess
{
Read = 1,
Write = 2,
Execute = 4
}
// 组合权限
FileAccess readWrite = FileAccess.Read | FileAccess.Write; // 1|2=3
//同时拥有读和写的权限
四.泛型
定义:
- 泛型是C# 2.0引入的一个特性,允许在定义类,接口,方法和委托时,使用类型参数,从而实现代码的类型安全和重用性
优势:
- 类型安全:在编译时检查类型,防止由于类型不匹配导致的运行时错误。
- 性能提升:避免了装箱(boxing)和拆箱(unboxing)的开销。
- 代码重用:编写一次代码,可适用于多种数据类型。
泛型的使用:
1.泛型类:定义一个泛型类,使用类型参数T
定义泛型类:
public class GenericClass<T>
{
private T _value;
public GenericClass(T value)
{
_value = value;
}
public T GetValue()
{
return _value;
}
}
使用泛型类:
GenericClass<int> intInstance = new GenericClass<int>(10);
int intValue = intInstance.GetValue(); // intValue = 10
GenericClass<string> stringInstance = new GenericClass<string>("Hello");
string stringValue = stringInstance.GetValue(); // stringValue = "Hello"
2.泛型方法:在方法定义中使用类型参数
定义泛型方法:
public class Utility
{
public void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}
}
使用泛型方法:
Utility utility = new Utility();
int x = 5, y = 10;
utility.Swap<int>(ref x, ref y); // 交换整数
string s1 = "First", s2 = "Second";
utility.Swap<string>(ref s1, ref s2); // 交换字符串
3.泛型接口
定义一个泛型接口:
public interface IRepository<T>
{
void Add(T item);
T Get(int id);
}
实现泛型接口:
public class Repository<T> : IRepository<T>
{
private List<T> _items = new List<T>();
public void Add(T item)
{
_items.Add(item);
}
public T Get(int id)
{
return _items[id];
}
}
五.委托及泛型委托
委托
定义:
- 委托是C#中的一种数据类型,它定义了一个方法的类型,使得方法可以作为参数传递。委托类似于函数指针,但它是类型安全的。
基本语法:public delegate 返回类型 委托名(参数列表);
定义委托:
public delegate int MathOperation(int a, int b);
使用委托:
public class Calculator
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
}
public class Program
{
// 定义一个委托类型
public delegate int Operation(int x, int y);
public static void Main()
{
Calculator calc = new Calculator();
// 创建委托实例并指向Add方法
Operation op = new Operation(calc.Add);
Console.WriteLine(op(3, 4)); // 输出: 7
// 改变委托指向Subtract方法
op = new Operation(calc.Subtract);
Console.WriteLine(op(10, 4)); // 输出: 6
}
}
泛型委托
使用泛型参数的委托类型,增强了委托的灵活性和可重用性
常用的泛型委托:
Func<T1,...,TResult>:有返回值的委托,可有0到16个输入参数
Func<int, int, int> multiply = (a, b) => a * b;
int product = multiply(3, 4); // product = 12
Action<T1,...>:无返回值的委托,可有0到16个输入参数。
Action<string> display = message => Console.WriteLine(message);
display("Hello, World!"); // 输出:Hello, World!
Predicate<T>:返回bool
类型的委托,常用于条件判断。
Predicate<int> isPositive = number => number > 0;
bool check = isPositive(5); // check = true
自定义泛型委托:
public delegate TOutput Converter<TInput, TOutput>(TInput input);
class Program
{
static void Main()
{
Converter<double, int> doubleToInt = num => (int)num;
int result = doubleToInt(3.14); // result = 3
}
}
六.事件
定义:
- 事件是委托的特殊形式,用于在对象之间传递消息或通知.当对象的状态发生改变时,可以通过事件通知订阅者.事件是基于“发布-订阅”(Publish-Subscribe)模式的实现
基本语法:public event 委托类型 事件名;
事件:
定义委托和事件:
// 定义委托
public delegate void NotifyEventHandler(string message);
// 定义发布者类
public class Publisher
{
// 声明事件
public event NotifyEventHandler Notify;
public void DoSomething()
{
// 执行某些操作
// 触发事件
OnNotify("事件被触发.");
}
protected virtual void OnNotify(string message)
{
// 检查是否有订阅者
Notify?.Invoke(message);
}
}
订阅事件:
// 定义订阅者类
public class Subscriber
{
public void OnNotified(string message)
{
Console.WriteLine($"Received message: {message}");
}
}
使用事件:
Publisher publisher = new Publisher();
Subscriber subscriber = new Subscriber();
// 订阅事件
publisher.Notify += subscriber.OnNotified;
// 触发事件
publisher.DoSomething(); // 输出:Received message: 事件被触发.
泛型事件:使用泛型委托(如EventHandler<TEventArgs>)来声明事件,可以传递更具体的事件数据。
使用EventHandler<TEventArgs>:
// 定义事件参数类
public class ProgressEventArgs : EventArgs
{
public int Percentage { get; set; }
}
// 定义发布者类
public class Process
{
// 声明泛型事件
public event EventHandler<ProgressEventArgs> ProgressChanged;
public void StartProcess()
{
for (int i = 0; i <= 100; i += 10)
{
// 模拟处理过程
// 触发事件
OnProgressChanged(i);
}
}
protected virtual void OnProgressChanged(int percentage)
{
ProgressChanged?.Invoke(this, new ProgressEventArgs { Percentage = percentage });
}
}
订阅泛型事件:
public class Listener
{
public void Subscribe(Process process)
{
process.ProgressChanged += OnProgressChanged;
}
private void OnProgressChanged(object sender, ProgressEventArgs e)
{
Console.WriteLine($"Process is {e.Percentage}% complete.");
}
}
使用泛型事件:
Process process = new Process();
Listener listener = new Listener();
listener.Subscribe(process);
process.StartProcess();
// 输出:
// Process is 0% complete.
// Process is 10% complete.
// ...
// Process is 100% complete.
七.事件,委托,泛型结合使用
代码示例:
// 定义泛型委托
public delegate void ValueChangedEventHandler<T>(object sender, ValueChangedEventArgs<T> e);
// 定义泛型事件参数类
public class ValueChangedEventArgs<T> : EventArgs
{
public T OldValue { get; set; }
public T NewValue { get; set; }
}
// 定义发布者类
public class ObservableProperty<T>
{
private T _value;
// 声明泛型事件
public event ValueChangedEventHandler<T> ValueChanged;
public T Value
{
get => _value;
set
{
if (!_value.Equals(value))
{
T oldValue = _value;
_value = value;
OnValueChanged(oldValue, _value);
}
}
}
protected virtual void OnValueChanged(T oldValue, T newValue)
{
ValueChanged?.Invoke(this, new ValueChangedEventArgs<T> { OldValue = oldValue, NewValue = newValue });
}
}
// 定义订阅者类
public class PropertyObserver<T>
{
public void Subscribe(ObservableProperty<T> property)
{
property.ValueChanged += OnValueChanged;
}
private void OnValueChanged(object sender, ValueChangedEventArgs<T> e)
{
Console.WriteLine($"Value changed from {e.OldValue} to {e.NewValue}");
}
}
使用示例:
ObservableProperty<string> nameProperty = new ObservableProperty<string> { Value = "Alice" };
PropertyObserver<string> observer = new PropertyObserver<string>();
observer.Subscribe(nameProperty);
nameProperty.Value = "Bob"; // 输出:Value changed from Alice to Bob
总结
-
泛型(Generics):允许在类,接口,方法和委托中使用类型参数,提高了代码的类型安全性和重用性
-
委托(Delegate):是用于引用方法的类型,支持将方法作为参数传递.泛型委托增强了委托的灵活性
-
事件(Event):基于委托的发布-订阅机制,用于在对象间发送通知和消息.泛型事件可以传递特定类型的数据,使事件处理更加强大和类型安全