一、ThreadStart Thread 有啥区别
ThreadStart
和 Thread
是.NET Framework中用于多线程编程的两个关键类。
1.ThreadStart:
ThreadStart
是一个委托类型,通常用于表示在一个新的线程上执行的方法。- 它是一个代表不带参数并且没有返回值的方法的委托。当你希望在新线程上执行某个方法时,可以使用
ThreadStart
来引用该方法。
2.Thread:
Thread
类是表示操作系统线程的实体。它允许你创建和控制线程的执行。- 通过创建
Thread
对象,你可以为该对象指定一个委托(例如,ThreadStart
委托),这个委托将在新线程上执行。
二、如何理解委托
委托(Delegate)是一种类型,它允许你将方法作为参数传递、存储在变量中,并在稍后执行这些方法。委托提供了一种间接调用方法的机制,使得可以在运行时动态地选择和调用不同的方法。以下是对委托的一些关键概念和理解:
1.类型安全的函数指针: 委托可以被看作是类型安全的函数指针。它可以引用一个或多个方法,并且在调用时会检查方法的签名(参数类型和返回类型),以确保类型匹配。
2. 方法的封装: 委托允许你将一个或多个方法封装到一个委托实例中。这样,你可以将委托实例传递给其他代码,使其能够调用委托引用的方法,而无需知道具体的方法是什么。
3. 多播委托: 委托可以组合多个方法,形成一个多播委托。当调用多播委托时,它会按照添加顺序依次调用每个委托引用的方法。
4. 异步编程: 委托在异步编程中有着重要的应用。通过委托,你可以将一个方法作为异步操作的回调函数传递,使得在异步操作完成时能够自动调用指定的方法。
5. 事件: 事件是委托的一种特殊用法,用于实现发布-订阅模型。事件允许对象通知其他对象某个事件的发生,而其他对象可以订阅并在事件发生时执行特定的操作。
理解委托的关键是将其视为一种可用于间接调用方法的类型。它提供了一种松散耦合的方式,使得你可以更灵活地设计和组织代码,尤其在涉及回调、事件处理和异步操作时非常有用。
三、typeof
在 C# 中,typeof
是一个关键字,用于获取指定类型的 System.Type
对象。System.Type
类提供有关类型的信息,包括类的成员、方法、属性等。
使用 typeof
关键字的语法如下:
Type type = typeof(YourType);
其中,YourType
是你要获取信息的类型。例如:
Type stringType = typeof(string);
Type intType = typeof(int);
这样就可以获取 string
和 int
类型的 Type
对象。
通常,typeof
主要用于在运行时获取类型信息,以进行反射操作。例如,你可以使用 typeof
结合反射来动态创建实例、调用方法、获取属性等。
Type personType = typeof(Person);
object personInstance = Activator.CreateInstance(personType);
MethodInfo method = personType.GetMethod("SomeMethod");
method.Invoke(personInstance, null);
上述示例中,typeof(Person)
获取了 Person
类型的 Type
对象,然后通过反射创建了该类型的实例并调用了其中的方法。
总的来说,typeof
在 C# 中是一个用于获取类型信息的关键字,它是许多反射操作的基础。
四、C# 属性字段get set 访问器介绍
属性定义
属性的定义通常包含以下部分:
private int _myField; // 私有字段
public int MyProperty
{
get
{
// get 访问器用于获取属性值
return _myField;
}
set
{
// set 访问器用于设置属性值
_myField = value;
}
}
上述代码中,MyProperty
是一个属性,通过 get
和 set
访问器提供对 _myField
字段的读写访问。
get 访问器
get
访问器用于获取属性的值。它包含在属性声明内部,并在访问属性时被自动调用。语法如下:
public int MyProperty
{
get
{
// 返回属性值的逻辑
return _myField;
}
}
set 访问器
set
访问器用于设置属性的值。它也包含在属性声明内部,当给属性赋值时自动调用。语法如下:
public int MyProperty
{
set
{
// 设置属性值的逻辑
_myField = value;
}
}
自动属性
在一些简单的情况下,C# 提供了自动属性,允许你在不显式定义字段的情况下声明属性。这样,编译器会自动创建一个私有字段并为你处理 get
和 set
访问器的实现。例如:
public int MyProperty { get; set; }
这样的写法等效于:
private int _myField;
public int MyProperty
{
get { return _myField; }
set { _myField = value; }
}
总的来说,属性是一种在类中用于封装字段的机制,通过 get
和 set
访问器可以控制对属性的读写访问。这提供了一种更灵活和安全的方式来访问和修改类的成员。
五、和null 相关的运算符
-
?.
运算符(null-conditional 运算符):- 该运算符允许你在访问可能为 null 的对象的成员时避免引发空引用异常(NullReferenceException)。
- 如果操作符左侧的操作数为 null,则整个表达式的结果为 null,否则就会计算右侧的成员或方法调用。
- 例如:
object?.Property
或object?.Method()
。
-
??
运算符(null 合并运算符):- 该运算符用于在左侧操作数为 null 时提供一个备用值。如果左侧操作数为 null,则整个表达式的结果为右侧操作数,否则就使用左侧操作数的值。
- 例如:
nullableValue ?? defaultValue
或stringValue ?? "Default"
。
示例:
// 使用 ?. 运算符
string name = person?.Name;
// 使用 ?? 运算符
string displayName = name ?? "Unknown";
在上面的示例中,person?.Name
表示如果 person
不为 null,则获取其 Name
属性的值,否则 name
将为 null。接着,name ?? "Unknown"
表示如果 name
不为 null,则使用 name
的值,否则 displayName
将为字符串 “Unknown”。
?.[]
运算符(null-conditional 索引器运算符):- 类似于
?.
运算符,但用于访问集合或数组的元素。 - 例如:
myArray?[index]
或myList?[0]
。
- 类似于
??=
运算符(null 合并赋值运算符):- 用于将右侧的值赋给左侧的变量,但只有当左侧变量为 null 时才执行赋值操作。
- 例如:
variable ??= expression
。
is
模式匹配运算符:- 用于检查一个对象是否为某个特定类型,并在检查的同时进行类型转换。
- 可以和
null
一起使用,例如:if (obj is MyClass myObj)
。
?.()
运算符(null-conditional 方法调用运算符):- 用于调用对象的方法,如果对象为 null,则整个表达式的结果为 null。
- 例如:
myObject?.MyMethod()
。
六、函数中的ref 和out
-
ref
关键字:-
ref
用于传递参数的引用。通过ref
关键字,可以使得函数能够修改调用方传递的变量的值。 -
使用
ref
关键字的参数必须在函数调用之前被初始化。 -
示例:
void ModifyValue(ref int x) { x = x * 2; } int num = 5; ModifyValue(ref num); // 现在,num 的值将变成 10
-
-
out
关键字:-
out
类似于ref
,也用于传递参数的引用。与ref
不同的是,使用out
的参数无需在函数调用之前被初始化。 -
函数在使用
out
关键字时必须确保在函数结束之前为out
参数赋值。 -
out
参数在函数内部必须赋值,否则会导致编译错误。 -
示例:
void InitializeValue(out int y) { y = 10; } int result; InitializeValue(out result); // 现在,result 的值将变成 10
-
总体来说,ref
和 out
关键字都用于在函数调用中传递参数引用,允许函数修改调用方的变量。ref
要求参数在调用前初始化,而 out
不要求。注意使用这两个关键字时应该小心,确保它们的使用场景和语义是合适的。
七、控件Panel
System.Windows.Forms.Panel 和System.Windows.Forms.TableLayoutPanel
-
System.Windows.Forms.Panel
:-
Panel
是一个容器控件,用于包含其他控件,并提供一个可视化的容器。它可以用作布局的容器,允许将其他控件放置在其内部。 -
Panel
通常用于将一组相关的控件组织在一起,并提供容器的外观和行为。你可以在Panel
上放置按钮、文本框、标签等控件,以便更好地组织和管理用户界面。 -
示例:
csharpCopy code// 创建一个 Panel Panel myPanel = new Panel(); // 将 Panel 添加到窗体上 this.Controls.Add(myPanel); // 在 Panel 上添加其他控件 Button myButton = new Button(); myPanel.Controls.Add(myButton);
-
-
System.Windows.Forms.TableLayoutPanel
:-
TableLayoutPanel
是一个表格布局控件,用于以表格形式排列子控件。它提供了一种方便的方式来创建和管理复杂的布局,其中子控件可以根据行和列的定义来进行布局。 -
TableLayoutPanel
允许你以行和列的方式添加和排列控件,可以轻松实现灵活的布局,适用于需要在多个方向上对控件进行排列的情况。 -
示例:
// 创建一个 TableLayoutPanel TableLayoutPanel myTableLayoutPanel = new TableLayoutPanel(); // 将 TableLayoutPanel 添加到窗体上 this.Controls.Add(myTableLayoutPanel); // 在 TableLayoutPanel 上添加子控件,并指定行和列 Button button1 = new Button(); myTableLayoutPanel.Controls.Add(button1, 0, 0); // 在第一行第一列 Button button2 = new Button(); myTableLayoutPanel.Controls.Add(button2, 1, 0); // 在第一行第二列
-
这两个控件都是 Windows Forms 提供的布局和容器控件,用于帮助你更方便地创建和管理用户界面。选择使用哪一个取决于你的具体需求和布局结构。Panel
更自由形式,而 TableLayoutPanel
更适合需要表格式布局的情况。