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
所指向的对象进行了变异
编辑:我看到你改变了你的问题。那么:
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
所指向的对象进行了变异
编辑:我看到你改变了你的问题。那么:
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”引用的对象`
someClassInstance
引用的对象的内容。这是一个操作中可变性的主要示例。如果此场景中的所有内容都是不可变的,则SomeName
的settnig将需要生成对象reference的副本通过someClassInstance
对其进行验证,并给它一个新值
someClassInstance.SomeName = "Now This is much more than a name";
CLR中的对象在默认情况下肯定不是不可变的。这里有一点混乱,因为您在示例中使用了
string
,这是一种实现为不可变类型的类型。但这肯定不是.Net中的默认值,而且易变性比不可变性更常见
以这条线为例
someClassInstance.RelatedNames.Add("HELLO!");
本sta中有3个感兴趣的对象