Все объекты неизменны внутри кучи? - PullRequest
0 голосов
/ 21 января 2012

Учитывая,

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' ?
     }
}

Как уже упоминалось в комментариях выше, «AFAIK» при изменении изменяемого объекта внутренние указатели этого объекта будут просто указывать на другую область памяти внутри кучи. Если это правильно, то означает ли это, что все объекты в куче (ссылочный тип) являются неизменяемыми?

Спасибо за ваш интерес.

Ответы [ 3 ]

4 голосов
/ 21 января 2012

Где изменчивость?Прямо здесь:

someClassInstance.SomeName = "Now This is much more than a name";
someClassInstance.RelatedNames = new List<string>(100} { "N","o","w".....};

Вы просто мутировали объект, на который указывает someClassInstance.

Кроме того, ваш пример немного надуманный.String действительно неизменны, но List нет, так что вы могли бы сделать это:

someClassInstance.RelatedNames.Add("HELLO!");

И тогда вы просто мутировали объект, на который указывает someClassInstance.RelatedNames.


РЕДАКТИРОВАТЬ: я вижу, вы изменили свой вопрос.Ну, тогда:

  1. someClassInstance.SomeName переместит свой указатель на другую строку внутри кучи
  2. someClassInstance.RealtedNames переместит свой указатель на другой список <> (101) внутрикуча.

1 верно, потому что String было , предназначено , чтобы быть неизменным.Вот почему есть класс StringBuilder на тот случай, если вам нужна изменяемая строка.

2 - false, потому что это не так, как реализован List.Возможно, отсюда и твоя путаница.Тем не менее, когда вы вызываете AddRange, someClassInstance.RelatedNames все равно будет указывать на тот же экземпляр, но внутреннее состояние этого экземпляра будет изменено (скорее всего, его резервный массив будет изменен, чтобы указывать на другой объект массива, и его счетчиктеперь будет 101).Фактически, ссылка не может волшебным образом изменяться в зависимости от операций, которые вызываются для объекта, на который она ссылается.

И ничто из этого не меняет того факта, что внутреннее состояние someClassInstance было изменено в любом случае.

1 голос
/ 21 января 2012

Объект в CLR определенно не является неизменным по умолчанию. Здесь есть небольшая путаница, потому что вы использовали string в своем примере, который является типом, который реализован как неизменяемый тип. Это, конечно, не по умолчанию в .Net, и изменчивость гораздо более распространена, чем неизменяемость.

Взять эту строку в качестве примера

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

В этом утверждении есть 3 объекта интереса.

  • Объект, на который ссылается someClassInstance.SomeName
  • Строка со значением "Now this is much more than a name"
  • Объект, на который ссылается someClassInstance.

Все 3 из этих значений живут в куче. Выполнение этого оператора приведет к изменению содержимого объекта, на который ссылается someClassInstance. Это яркий пример изменчивости в действии. Если бы все в этом сценарии было неизменным, тогда для урегулирования SomeName необходимо было бы создать копию объекта, на который ссылается someClassInstance, и присвоить ему новое значение. Это не происходит здесь и может быть продемонстрировано следующим

var obj = someClassInstance;  // Both reference the same object
someClassInstance.SomeName = "hello";
Console.WriteLine(someClassInstance.SomeName): // Prints "hello"
0 голосов
/ 21 января 2012

Да, потому что они помещаются в кучу с помощью new или malloc и являются указателями.Таким образом, вы можете только добавлять или удалять ссылки указателя.Таким образом, технически сами объекты не являются неизменяемыми, поскольку они не находятся в куче с самого начала, но распределение указателей в куче является неизменным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...