C# 堆内的所有对象都是不可变的吗?

C# 堆内的所有对象都是不可变的吗?,c#,heap,immutability,C#,Heap,Immutability,鉴于 公共类SomeClass{ 公共字符串SomeName{get;} 公共列表相关名称{get;} } 公共课程{ 公共图书馆{ var someClassInstance=new SomeClass(){SomeName=“A”,RelatedNames=new List(1){“A”}; //所以,现在someClassInstance已经在heap=1 string对象和一个包含1 string对象的列表中分配了一些内存。 //因为SomeClass是可变的,所以可以如下修改 some

鉴于

公共类SomeClass{
公共字符串SomeName{get;}
公共列表相关名称{get;}
}
公共课程{
公共图书馆{
var someClassInstance=new SomeClass(){SomeName=“A”,RelatedNames=new List(1){“A”};
//所以,现在someClassInstance已经在heap=1 string对象和一个包含1 string对象的列表中分配了一些内存。
//因为SomeClass是可变的,所以可以如下修改
someClassInstance.SomeName=“现在这不仅仅是一个名称”;
someClassInstance.RelatedNames=someClassInstance.RelatedNames.AddRange(新列表(100}{“N”、“o”、“w”…});
//现在堆内发生了什么?
//1.someClassInstance.SomeName将其指针移动到堆内的另一个字符串
//2.someClassInstance.RealtedNames将其指针移动到堆内的另一个列表(101)。
//这是正确的吗?那么“可变性”在哪里呢?
}
}
如上所述,修改可变对象时,“AFAIK”该对象的内部指针只会指向堆内的另一个内存位置。如果这是正确的,那么这是否意味着堆内的所有对象(引用类型)都是不可变的


感谢您的关注。

可变性在哪里?就在那里:

public class SomeClass {
     public string SomeName{get;}
     public List<string> RelatedNames{get;}
}

public class Program{
     public void Main(){
          var someClassInstance = new SomeClass(){ SomeName = "A", RelatedNames = new List<string>(1){ "a" }};
          // So, now someClassInstance have been allocated some memory in heap = 1 string object and a list with 1 string object.

          // Since SomeClass is mutable, it could be modified as below
          someClassInstance.SomeName = "Now This is much more than a name";
          someClassInstance.RelatedNames = someClassInstance.RelatedNames.AddRange(new List<string>(100} { "N","o","w".....});

         //Now what happens inside heap?
         //1.someClassInstance.SomeName will move it's pointer to another string inside heap
         //2.someClassInstance.RealtedNames will move it's pointer to another List<>(101) inside heap.
         //Is it correct? Then where is 'mutability' ?
     }
}

然后,您只是对
someClassInstance.RelatedNames
所指向的对象进行了变异


编辑:我看到你改变了你的问题。那么:

  • someClassInstance.SomeName将其指针移动到堆内的另一个字符串
  • someClassInstance.RealtedNames将其指针移动到堆内的另一个列表(101)
  • 1
    是真的,因为
    String
    被设计为不可变的。这就是为什么会有
    StringBuilder
    类,以防您需要可变字符串

    2
    为false,因为这不是
    List
    的实现方式。也许这就是您的困惑所在。不过,当您调用
    AddRange
    时,
    someClassInstance。RelatedNames
    仍将指向同一实例,但该实例的内部状态将发生更改(最有可能的情况是,它的支持数组将被更改为指向不同的数组对象,其计数现在将为
    101
    )。事实上,引用不能基于对它引用的对象调用的操作而神奇地更改


    所有这些都没有改变这样一个事实,即某个ClassInstance的内部状态无论如何都发生了变异。

    可变性在哪里?就在那里:

    public class SomeClass {
         public string SomeName{get;}
         public List<string> RelatedNames{get;}
    }
    
    public class Program{
         public void Main(){
              var someClassInstance = new SomeClass(){ SomeName = "A", RelatedNames = new List<string>(1){ "a" }};
              // So, now someClassInstance have been allocated some memory in heap = 1 string object and a list with 1 string object.
    
              // Since SomeClass is mutable, it could be modified as below
              someClassInstance.SomeName = "Now This is much more than a name";
              someClassInstance.RelatedNames = someClassInstance.RelatedNames.AddRange(new List<string>(100} { "N","o","w".....});
    
             //Now what happens inside heap?
             //1.someClassInstance.SomeName will move it's pointer to another string inside heap
             //2.someClassInstance.RealtedNames will move it's pointer to another List<>(101) inside heap.
             //Is it correct? Then where is 'mutability' ?
         }
    }
    

    然后,您只是对
    someClassInstance.RelatedNames
    所指向的对象进行了变异


    编辑:我看到你改变了你的问题。那么:

  • someClassInstance.SomeName将其指针移动到堆内的另一个字符串
  • someClassInstance.RealtedNames将其指针移动到堆内的另一个列表(101)
  • 1
    是真的,因为
    String
    被设计为不可变的。这就是为什么会有
    StringBuilder
    类,以防您需要可变字符串

    2
    为false,因为这不是
    List
    的实现方式。也许这就是您的困惑所在。不过,当您调用
    AddRange
    时,
    someClassInstance。RelatedNames
    仍将指向同一实例,但该实例的内部状态将发生更改(最有可能的情况是,它的支持数组将被更改为指向不同的数组对象,其计数现在将为
    101
    )。事实上,引用不能基于对它引用的对象调用的操作而神奇地更改


    所有这些都不能改变这样一个事实,即
    someClassInstance
    的内部状态无论如何都发生了变化。

    是的,因为它们是使用new或malloc放在堆上的,并且是指针。因此,您只能添加或删除指针引用。因此从技术上讲,对象本身并不是不可变的,因为它们一开始就不在堆上,但堆上的指针分配是不可变的。

    是的,因为它们是使用new或malloc放在堆上的,并且是指针。因此,您只能添加或删除指针引用。因此从技术上讲,对象本身不是不可变的,因为它们一开始不在堆上,但堆上的指针分配是不可变的CLR中的le.

    对象在默认情况下肯定不是不可变的。这里有一点混乱,因为您在示例中使用了
    string
    ,它是一种实现为不可变类型的类型。但这肯定不是.Net中的默认值,而且易变性比不可变性更常见

    以这条线为例

    someClassInstance.RelatedNames.Add("HELLO!");
    
    本声明中有3个相关对象

    • someClassInstance.SomeName
    • 值为“
      ”的字符串现在不仅仅是一个名称“
    • “someClassInstance”引用的对象`
    所有这3个值都存在于堆中。此语句的执行将改变
    someClassInstance
    引用的对象的内容。这是一个操作中可变性的主要示例。如果此场景中的所有内容都是不可变的,则
    SomeName
    的settnig将需要生成对象reference的副本通过
    someClassInstance
    对其进行验证,并给它一个新值

    someClassInstance.SomeName = "Now This is much more than a name";
    

    CLR中的对象在默认情况下肯定不是不可变的。这里有一点混乱,因为您在示例中使用了
    string
    ,这是一种实现为不可变类型的类型。但这肯定不是.Net中的默认值,而且易变性比不可变性更常见

    以这条线为例

    someClassInstance.RelatedNames.Add("HELLO!");
    
    本sta中有3个感兴趣的对象