【问题标题】:What the different about the declaring variable in For loop or out?For循环或out中的声明变量有什么不同?
【发布时间】:2020-08-15 13:57:36
【问题描述】:
  1. 为什么方法 Calcu1 与 ILSpy 中的方法 Calcu2 具有相同的代码,而其他方法则没有?

  2. 虽然它们是不同的类型(其中一些是引用类型,另一些是值类型),为什么方法Calcu3是唯一具有不同hashcode的方法?其他人声明和操作的是同一个变量吗?

    class Program {
    static void Main(string[] args) {
        Calcu8();
    }
    
    static void Calcu1() {
        int single;
        for (int i = 0; i < 10; i++) {
            single = 5;
            Console.WriteLine(single + i);
        }
    }
    
    //Method Calcu2 has the same code as Method Calcu1 in ILSpy
    static void Calcu2() {
        for (int i = 0; i < 10; i++) {
            int single = 5;
            Console.WriteLine(single + i);
        }
    }
    
    //class type
    static void Calcu3() {
        for (int i = 0; i < 10; i++) {
            Student stu = new Student();
            stu.Name = "Tim";
            //not the same
            Console.WriteLine(stu.GetHashCode());
        }
    }
    
    //class type
    static void Calcu4() {
        Student stu = new Student();
        for (int i = 0; i < 10; i++) {
            stu.Name = "Tim";
            //same
            Console.WriteLine(stu.GetHashCode());
        }
    }
    
    //string
    static void Calcu5() {
        string str = string.Empty;
        for (int i = 0; i < 10; i++) {
            str = "Hello";
            //same
            Console.WriteLine(str.GetHashCode());
        }
    }
    
    //string
    static void Calcu6() {
        for (int i = 0; i < 10; i++) {
            string str = string.Empty;
            str = "Hello";
            //same
            Console.WriteLine(str.GetHashCode());
        }
    }
    
    //struct
    static void Calcu7() {
        Person per = new Person();
        for (int i = 0; i < 10; i++) {
            per.Name = "Tim";
            //same
            Console.WriteLine(per.GetHashCode());
        }
    }
    
    //struct
    static void Calcu8() {
        for (int i = 0; i < 10; i++) {
            Person per = new Person {
                Name = "Tim"
            };
            //same
            Console.WriteLine(per.GetHashCode());
        }
    }
    

    }

    公开课学生{ 公共字符串名称; }

    公共结构人{ 公共字符串名称; }

【问题讨论】:

  • 因为值类型的代码正在被优化,但引用类型的代码却不能,它与 new Student() 的实例化一次和在循环体中的工作方式不同。因此,1 个实例与 10 个实例之间存在差异。 struct 不是 by-ref 类型,它在此处的行为类似于 int

标签: c#


【解决方案1】:

首先,让我指出您的方法之间的区别:

方法Calcu1Calcu4Calcu5Calcu7:变量已在循环外声明并设置在循环内。该值将出现在循环之外。

方法Calcu2Calcu3Calcu6Calcu8:变量已在循环内声明,在循环外将不可用。

Calcu3 的 hashCode 发生变化,因为您每次都在创建不同的对象。通过 new 创建Student,堆栈将引用堆上的新对象。此引用每次都在更改,因为您要创建 10 个新对象。

你的Calcu8的hashCode不一样,因为它是struct,结构体保存在堆上。

请参阅here 了解有关堆栈的更多信息。在这一方面,您还可以找到堆上和栈上的定义。

在堆栈上:

使用以下类型声明列表声明的“事物”是值类型 (因为它们来自 System.ValueType): bool, byte, char, decimal, double, enum, float, int, long, sbyte, short, struct, uint, ulong, ushort

在堆上:

使用以下类型声明列表声明的“事物”是引用类型 (并且从 System.Object 继承......当然,除了作为 System.Object 对象的对象): 类、接口、委托、对象、字符串

【讨论】:

  • 非常感谢,兄弟。但我还有几个问题。 1.Calcu8 的hashcode 在我的测试中是相同的,并且您的话也支持“因为它是一个结构并且结构保存在堆上”。 2.为什么ValueType不能在for循环中一次又一次地保存在堆上?
  • 值类型可以分配在堆栈或堆上。引用类型不能堆栈分配。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-25
  • 2011-05-28
相关资源
最近更新 更多