C#类的成员初始化顺序

首先我们来看看引用类型的成员初始化过程

   我们来看一个例子吧

class Program
{
    static void Main(string[] args)
    {
        DriveB d = new DriveB();
    }
}

class BaseA
{
    static DisplayClass a = new DisplayClass("基类静态成员初始化");

    DisplayClass BaseA_c = new DisplayClass("基类实例变量BaseA_c初始化");

    public BaseA()
    {
        Console.WriteLine("基类构造方法被调用");
    }
}

class DriveB : BaseA
{
    static DisplayClass DriveB_b = new DisplayClass("继承类静态成员DriveB_b初始化");

    //static BaseA DriveB_a = new BaseA();

    DisplayClass DriveB_c = new DisplayClass("继承类实例变量DriveB_c初始化");

    public DriveB()
    {
        Console.WriteLine("继承类构造方法被调用");
    }
}
class DisplayClass
{
    public DisplayClass(string diplayString)
    {
        Console.WriteLine(diplayString);
        Console.WriteLine();
    }
}
程序动行的结果是:
继承类静态成员DriveB_b初始化
继承类实例变量DriveB_c初始化
基类静态成员初始化
基类实例变量BaseA_c初始化
基类构造方法被调用
继承类构造方法被调用

得出初始化顺序结论:

1)继承类静态成员变量初始化
2)继承类实例变量初始化
3)基类静态静态成员变量初始化
4)基类实例变量初始化
5)基类构造方法调用
6)继承类构造方法调用。

    好像结果和JAVA的有点不一样啊, 有点混乱的感觉,搞不懂M$为什么要让初始化按这样的顺序执行,像JAVA那样严格的从基类到派生类多好呀.上例的运行结果说明, 构造函数这么这个和我们通常思路执行的顺序还是有一定的差别.对于实例成员初始化,基本上就是以下步骤执行:
1 类的对象初始化大体顺序上实例成员赋值到构造函数
2 成员赋值初始化按照由子类到父类的顺序
3 构造函数的初始化按照由父类到子类的顺序
从这里我们有一点需要注意的是,因为成员赋值初始化是从子类到父类的,所以在子类的成员赋值初始化的过程中,不要引用父类定义的成员,因为这个时候父类成员还没有开始初始化.需要说明一点的是C#在创建对象的第一步分配内存完成后会动把所有实例成员变量初始化成变量的默认值,例如整型就是0,引用类型就是null.然后才开始进行成员变量初始化的过程.

 

C#对象初始化

1.     先变量后构造函数。变量先被初始化,然后构造函数被执行

2.     先静态化后实例化。当一个类被访问时,静态变量和构造函数最先被初始化.接着是对象的实例化变量和构造函数被初始化

3.     先派生类后基类。对于变量和静态构造函数,派生对象在基对象之前被初始化.比如C类派生自B,B类派生自A,那么变量和静态构造函数被初始化次序是C-B-A.

4.     除了实例构造函数。对于实例构造函数,基类构造函数在派生类构造函数之前执行,实例构造函数被执行次序是A-B-C.

5.     不要假定变量的次序。Fields依据它们在源文件中的声明的顺序依次初始化.然而,自从程序员和工具可以随意安排变量的声明后,你不应该在依靠变量任何特别的次序初始化

6.     对虚方法用两个阶段的构建。避免从一个构造器调用虚方法. 如果在初始化一个对象时需要调用一些虚方法,应在完整构造该对象的地方使用两阶段的构建,并随后调用已构造对象的初始化方法。

<think>我们正在讨论C#成员初始化顺序以及如何使用for循环进行赋值。根据引用[4],C#初始化顺序涉及静态成员、实例成员以及构造函数(包括静态构造函数和实例构造函数)的调用顺序。特别要注意的是,静态成员首次被使用前初始化,实例成员则在创建对象时初始化。用户的问题包含两部分:1.成员初始化顺序2.使用for循环对成员进行赋值的示例我们将分两部分回答:第一部分:成员初始化顺序(简要概述)第二部分:提供一个使用for循环对成员(例如数组)进行赋值的示例注意:成员初始化顺序通常由它们在中声明的顺序决定,但实际初始化发生在构造函数执行之前(对于实例成员)或静态构造函数执行之前(对于静态成员)。然而,在构造函数中,我们可以使用循环来对成员(如数组)进行赋值。示例说明:假设我们有一个,其中包含一个整型数组成员,我们想在构造函数中使用for循环来初始化这个数组。根据引用[1]和[3],数组可以在声明时初始化,也可以在构造函数中初始化。这里我们将展示在构造函数中使用for循环进行初始化。另外,引用[4]提到实例构造函数的顺序初始化(如果有),然后初始化当前的实例成员(按照声明顺序),最后执行当前的构造函数体。因此,在构造函数体内,我们可以安全地使用循环来为数组赋值,因为此时数组已经被分配了内存(通过new操作符)。我们创建一个名为MyClass的,其中包含一个int数组,并在构造函数中使用for循环给数组的每个元素赋值。代码示例:```publicclassMyClass{//声明一个数组,但不在声明时初始化(或者也可以初始化为null,然后在构造函数中初始化)publicint[]MyArray;//构造函数,参数n表示数组大小publicMyClass(intn){//初始化数组,分配内存MyArray=newint[n];//使用for循环为数组的每个元素赋值for(inti=0;i<n;i++){MyArray[i]=i*10;//示例赋值,可以根据需要修改}}}```使用方式:```classProgram{staticvoidMain(string[]args){//创建MyClass的实例,数组大小为5MyClassobj=newMyClass(5);//输出数组内容for(inti=0;i<obj.MyArray.Length;i++){Console.WriteLine($"MyArray[{i}]={obj.MyArray[i]}");}}}```输出:MyArray[0]=0MyArray[1]=10MyArray[2]=20MyArray[3]=30MyArray[4]=40注意:在构造函数中,我们首通过`newint[n]`为数组分配内存,然后使用for循环进行赋值。这样确保数组在对象创建时被正确初始化。另外,如果中有多个数组或集合需要初始化,也可以使用似的方法。引用[3]中提到了列表的初始化,我们同样可以在构造函数中使用循环来添加元素。例如,使用List<int>:```publicclassMyClassWithList{publicList<int>MyList;publicMyClassWithList(intn){MyList=newList<int>();for(inti=0;i<n;i++){MyList.Add(i*10);}}}```总结:1.成员初始化顺序:静态成员->基构造函数->实例成员(按照声明顺序初始化)->当前构造函数体。2.在构造函数体内,我们可以使用循环对成员(如数组或列表)进行赋值。相关问题:1.在C#中,如果成员是数组,除了在构造函数中初始化,还有哪些初始化方式?2.如何确保在多级继承中,基和派生的数组成员都能正确初始化?3.在C#中,静态数组的初始化有什么特殊要求?如何使用循环初始化静态数组?注意:静态数组的初始化必须在静态构造函数中或声明时进行,因为静态成员被首次使用前初始化,且不能通过实例构造函数初始化(因为静态成员属于,不属于实例)。参考文献:[^1]:数组的声明和初始化示例。[^3]:中列表初始化的示例。[^4]:初始化顺序的说明。</think>### C# 成员初始化顺序与 for 循环赋值示例 在 C# 中,成员初始化顺序遵循严格规则[^4]: 1. **静态成员初始化**:静态字段和静态构造函数最执行 2. **基初始化**:若有继承关系,执行基构造函数 3. **实例成员初始化**:按声明顺序初始化实例字段 4. **构造函数体执行**:最后执行当前的构造函数体 #### for 循环赋值的成员示例 ```csharp public class MatrixProcessor { // 1. 静态成员初始化(最执行) private static readonly int MaxSize = 100; // 2. 实例成员初始化(按声明顺序) private int[,] _matrix; private int[] _rowSums; private int _totalSum; // 构造函数(最后执行) public MatrixProcessor(int rows, int cols) { // 使用 for 循环初始化二维数组 _matrix = new int[rows, cols]; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { _matrix[i, j] = (i * cols) + j; // 按行列索引赋值 } } // 使用 for 循环计算行和 _rowSums = new int[rows]; for (int i = 0; i < rows; i++) { int sum = 0; for (int j = 0; j < cols; j++) { sum += _matrix[i, j]; } _rowSums[i] = sum; _totalSum += sum; // 累加总和 } } public void PrintResults() { Console.WriteLine($"总行数: {_rowSums.Length}"); for (int i = 0; i < _rowSums.Length; i++) { Console.WriteLine($"行 {i} 总和: {_rowSums[i]}"); } Console.WriteLine($"矩阵总和: {_totalSum}"); } } // 使用示例 class Program { static void Main() { var processor = new MatrixProcessor(3, 4); processor.PrintResults(); } } ``` #### 初始化顺序验证: ```csharp public class InitializationOrderDemo : BaseClass { // 静态字段(最初始化) private static string _staticField = "静态字段".PadRight(10); // 实例字段(按声明顺序初始化) private string _field1 = "字段1".PadRight(10); private string _field2 = "字段2".PadRight(10); public InitializationOrderDemo() { Console.WriteLine("构造函数执行"); Console.WriteLine($"{_staticField} | {_field1} | {_field2}"); } } public class BaseClass { public BaseClass() => Console.WriteLine("基构造函数"); } /* 输出顺序: 基构造函数 字段1初始化 字段2初始化 构造函数执行 静态字段 | 字段1 | 字段2 */ ``` #### 关键要点: 1. **for 循环最佳位置**:应在构造函数中进行复杂初始化(如嵌套循环),确保成员已分配内存[^1][^3] 2. **数组初始化**:必须用 `new` 分配内存才能使用循环赋值[^1] 3. **成员访问顺序**: - 静态字段可在声明时直接初始化 - 实例字段可在声明时简单初始化,复杂逻辑需在构造函数中完成 4. **继承场景**:派生的循环初始化应在基初始化后执行[^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值