目录
只会记录与其他语言稍有不同或者说特有的部分,因为一门编程语言,相同的功能可能表现形式不同,可能为了更加简便提供类似语法糖的特性。
特性
简介
- 特性(Attribute)是用于在运行时传递程序中各种元素(比如类、方法、枚举、属性等)的行为信息的声明性标签
- 规定特性的语法如下:
// 特性位于应用的元素之前,应用的元素比如说类,方法
[attribute(positional_parameters, name_parameter = value, ...)]
预定义特性
- [Obsolete]:标记为过时的特性,提示该方法或类已被弃用
- [Serializable]:使类可以被序列化
- [NonSerialized]:与 [Serializable] 一起使用,用于指定不希望序列化的字段
- [DllImport]
- [Conditional]:用于指定在满足特定条件下才编译的方法(条件编译)
- [AttributeUsage]:用于定义自定义特性的使用范围和限制,这个预定义特性用于自定义特性。
- 规定该特性的语法为:
[AttributeUsage( validon, // 这个参数规定自定义的特性可以应用的元素,比如说类,方法 AllowMultiple=allowmultiple, // 该特性是否可以多次使用 Inherited=inherited // 该特性是否可以被派生类继承 )]- 示例:
namespace test_c { [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)] class AnatationAttribute : Attribute { public AnatationAttribute(string description) { this.description = description; } protected string description; public string Description { get { return description; } } } [Anatation("这是程序入口的主类")] [Anatation("这是程序入口的主类")] class Application { [Anatation("入口方法为Main")] static void Main(string[] args) { } } } - [Flags]:用于定义枚举类型,使其可以被当作位域处理
- [DefaultValue]:指定字段的默认值
- [Description]:常用于添加属性或方法的描述信息
自定义特性
自定义特性的使用包含以下步骤:
- 自定义特性的定义:一个自定义的特性类应继承自System.Attribute 类
- 在目标程序元素上应用自定义特性:将自定义特性置于需要应用的元素之上
- 通过反射访问特性
反射
反射指程序可以访问、检测和修改它本身状态或行为的一种能力。
- 示例:使用反射获取类的自定义特性
using System;
using System.Reflection;
public class SampleClass
{
public string Name { get; set; }
[Obsolete("This method is obsolete.")]
public void OldMethod()
{
Console.WriteLine("This is an old method.");
}
public void NewMethod()
{
Console.WriteLine("This is a new method.");
}
}
public class Program
{
public static void Main(string[] args)
{
// 获取SampleClass类型的信息
Type type = typeof(SampleClass);
// 输出类名
Console.WriteLine("Class Name: " + type.Name);
// 获取并输出属性信息
PropertyInfo[] properties = type.GetProperties();
foreach (var prop in properties)
{
Console.WriteLine("Property Name: " + prop.Name + ", Property Type: " + prop.PropertyType);
}
// 获取并输出方法信息
MethodInfo[] methods = type.GetMethods();
foreach (var method in methods)
{
Console.WriteLine("Method Name: " + method.Name);
// 检查方法是否有特性
foreach (var attr in method.GetCustomAttributes())
{
Console.WriteLine(" - Attribute: " + attr.GetType().Name);
}
}
}
}
// 输出如下
Class Name: SampleClass
Property Name: Name, Property Type: System.String
Method Name: get_Name
- Attribute: CompilerGeneratedAttribute
Method Name: set_Name
- Attribute: CompilerGeneratedAttribute
Method Name: OldMethod
- Attribute: ObsoleteAttribute
Method Name: NewMethod
Method Name: Equals
- Attribute: __DynamicallyInvokableAttribute
Method Name: GetHashCode
- Attribute: __DynamicallyInvokableAttribute
Method Name: GetType
- Attribute: SecuritySafeCriticalAttribute
- Attribute: __DynamicallyInvokableAttribute
Method Name: ToString
- Attribute: __DynamicallyInvokableAttribute
属性
属性是类和结构体中用于封装数据的成员
set,get访问器
一种简化写法,等同于语法糖
- 只读属性:需要属性只读,则不写set访问器
- 只写属性:需要属性只写,则不写get访问器
class Test
{
private string name;
private int age;
// 只读属性name
public string Name
{
get { return name; }
}
// 只写属性age
public int Age
{
set { age = value; }
}
public int getAge()
{
return age;
}
public Test(string name, int age)
{
this.name = name;
this.age = age;
}
}
class Application
{
static void Main(string[] args)
{
Test test = new Test("Nrvcer", 24);
Console.WriteLine("Name: " + test.Name);
test.Age = 25;
Console.WriteLine("Age: " + test.getAge());
}
}
抽象属性
- 抽象类可拥有抽象属性,这些属性应在派生类中被实现
- 示例如下:
abstract class Person
{
public abstract string Name { get; set; }
public abstract int Age { get; set; }
}
class Student : Person
{
public override string Name { get; set; }
public override int Age { get; set; }
public override string ToString()
{
return "Name: " + Name + ", Age: " + Age;
}
}
class Application
{
static void Main(string[] args)
{
Student student = new Student { Name = "Nrvcer", Age = 24 };
Console.WriteLine(student.ToString());
}
}
索引器
- 索引器允许一个对象可以像数组一样使用下标的方式来访问。和get,set访问器不同的是前者返回或者设置一个特定的成员变量,而索引器返回或者设置对象实例的一个特定值
- 一维索引器的定义语法如下:
element-type this[int index]
{
// get 访问器
get
{
// 返回 index 指定的值
}
// set 访问器
set
{
// 设置 index 指定的值
}
}
- 索引器示例如下:
class Test
{
private string[] arr = new string[number];
public static int number = 10;
public Test()
{
for (int i = 0; i < number; i++) {
arr[i] = "Hello World!";
}
}
public string this[int index]
{
get {
if (index < 0 || index >= number) {
throw new IndexOutOfRangeException();
}
return arr[index];
}
set {
if (index < 0 || index >= number) {
throw new IndexOutOfRangeException();
}
arr[index] = value;
}
}
}
class Application
{
static void Main(string[] args)
{
Test t = new Test();
t[6] = "test";
for (int i = 0; i < Test.number; i++)
{
Console.WriteLine(t[i]);
}
}
}
- 索引器的重载:索引器的参数可以是其他类型的
集合
C#对各种数据结构,如栈,队列,列表,哈希表等都已实现,放置在System.Collections命名空间下。详情略。
泛型
- 泛型接口
- 泛型类
- 泛型方法
- 泛型事件
- 泛型委托:示例如下
using System;
namespace test_c {
public delegate void PrintDelegate<T>(T t);
class Application {
public void print_string(string str)
{
Console.WriteLine(str);
}
public void print_int(int num)
{
Console.WriteLine(num);
}
static void Main(string[] args) {
PrintDelegate<string> print_string_delegate = new PrintDelegate<string>(new Application().print_string);
PrintDelegate<int> print_int_delegate = new PrintDelegate<int>(new Application().print_int);
print_string_delegate("Hello World");
print_int_delegate(100);
Console.ReadKey();
}
}
}
委托
基础
在 C# 中,委托(Delegate)是一种类型安全的函数指针,可以指向任何与其签名匹配的方法,它允许将方法作为参数传递给其他方法。
- 委托的声明:一般声明在外面,与类是平级的
public delegate <return type> <delegate-name> <parameter list>
- 委托变量的创建:
<delegate-name> 变量名 - 委托方法定义:委托方法的原型需要和委托一致
- 委托变量绑定委托方法进行实例化:使用
new delegate-name(被委托的方法名)语法进行委托的实例化- 委托的单播:一个委托变量只需要绑定一个方法
class Test { public delegate int add(int a, int b); } class Application { static void Main(string[] args) { Test t = new Test(); Test.add ad = new Test.add(add); Console.WriteLine(ad(2, 3)); } static int add(int a, int b) { return a + b; } }- 委托的多播:使用
+运算符将相同类型的委托合并到一个委托中,这个委托调用时,相同类型的委托关联的方法被调用。如果你不再需要某个方法,可以通过-=运算符将该方法从委托链中移除
- 委托的调用
内置委托
- Action:代表不返回值的方法
- Func:代表有返回值的方法
- Predicate:代表返回 bool 值的方法
应用场景
- 基于委托实现主窗体向子窗体传值
- 基于委托实现子窗体向主窗体传值
事件
简介
- 事件本质上就是一个委托类型,其使用发布-订阅模型,利用委托来存储和调用多个订阅方法
- 事件是一个存储委托方法的私有字段,编译自会自动生成add和remove方法来管理委托列表
事件的使用
- 委托的声明:定义事件将使用的委托类型
- 事件的声明:通过event关键字声明一个事件
- 事件的触发:在合适的时机调用事件,通知所有订阅者(调用委托的方法列表)
- 事件的订阅和取消订阅:通过
+=和-=运算符订阅和取消订阅事件 - 示例如下:
// 泛型委托
public delegate void ClickEventHandler<T>(object sender, T args);
class PushButton<T>
{
// 定义泛型事件
public event ClickEventHandler<T> clicked;
public void TriggerEvent(T args)
{
clicked ?. Invoke(this, args); // 触发事件
}
}
class Application
{
static void Main(string[] args)
{
PushButton<string> button = new PushButton<string>();
button.clicked += (sender, message) => Console.WriteLine("Button clicked with args: " + message);
// 用户点击按钮
button.TriggerEvent("user click button");
Console.ReadKey();
}
}
事件机制实现线程之间的通信。
不安全代码
托管代码与非托管代码
- 托管代码:由.NET语言运行环境(CLR,Common Language Runtime)管理的代码。CLR 提供了内存管理、类型安全性、异常处理等服务,开发者无需直接操心底层资源的分配和释放。
- 非托管代码:非托管代码是直接运行在操作系统上的代码,不依赖 CLR 提供的服务。开发者需要手动管理内存、资源分配和释放,容易出现资源泄漏或访问非法内存的问题。例如C#程序中使用
[DllImport("xxx.dll")]特性调用C++语言编写的DLL函数时,就使用了非托管代码。
不安全代码
- 定义:指允许直接使用指针(pointer)和操作内存的代码块。这样的代码块使用
unsalf修饰符进行标记 - 实例:在C#中使用不安全代码实现两个整型值的交换
class Program
{
public unsafe static void swap(int* p, int* q)
{
int temp = *p;
*p = *q;
*q = temp;
}
static void Main(string[] args)
{
unsafe
{
int a = 10, b = 20;
Console.WriteLine("a = {0}, b = {1}", a, b);
swap(&a, &b);
Console.WriteLine("a = {0}, b = {1}", a, b);
}
}
}
- 在不安全代码中,如果你需要操作托管类型(如数组、字符串等),它们的内存位置可能会被垃圾回收器移动,因此需要使用 fixed 关键字固定其内存地址。
public unsafe static void Main()
{
int[] list = { 10, 100, 200 };
fixed (int* ptr = list)
for (int i = 0; i < list.Length; i++)
{
Console.WriteLine("Address of list[{0}]={1}", i, (int)(ptr + i));
Console.WriteLine("Value of list[{0}]={1}", i, *(ptr + i));
}
Console.ReadKey();
}
多线程
略
关键字
- partial:用于将一个类、结构体、接口或方法的定义拆分到多个文件中。它允许你将一个类型的实现分散在多个文件中。示例如下:
// 一个文件中
public partial class SerialBus
{
public string portName
{
get { return portName; }
set { portName = value; }
}
}
// 另一个文件中
public partial class SerialBus
{
public string info() {
return "port:COM1";
}
}
// OK
SerialBus serialBus = new SerialBus();
Console.WriteLine(serialBus.info());
浙公网安备 33010602011771号