Когда свойство get вызовет создание локальной копии ссылочного типа? Как этого избежать? - PullRequest
0 голосов
/ 19 августа 2010

В классе fooBase есть SomeProperty.В классе barBase у меня есть поле типа fooBase:

public class fooBase 
{
    public object SomeProperty { get; set; }
}

public class barBase
{
    protected fooBase _foo;
}

Понятно, что из barBase я могу изменить SomeProperty на _foo.SomeProperty = whatever;.

Теперь в производномВ классе fooChild существует некоторая неважная логика, в которой работает производный класс barChild.Конструктор barChild получает экземпляр fooChild и сохраняет его.

public class fooChild : fooBase { /* someLogic */ }

public class barChild : barBase
{
    public barChild(fooChild foo)
    {
        _foo = foo; // foo of [fooChild] type stored in _foo of [fooBase] type.
    }

    protected fooChild _getFoo // cast via 'as' to access fooChild logic
    { get { return _foo as fooChild; } }
}

Теперь, чтобы использовать логику fooChild, мне нужен доступ к _foo as fooChild (что делает _getFoo).

Вопрос : get { return ... as ... } создаст локальную копию _foo, чтобы при вызове SomeFunction() в производном классе barChild изменение свойства SomeProperty не происходило в barBase._foo?

public class somewhereElse : barChild
{
    public void SomeFunction()
    {
        _getFoo.SomeProperty = new object();
        // now barBase:_foo.SomeProperty is still old object?
    }
}

Если да, как я могу избежать этого?
Если нет, как я могу сказать?

Ответы [ 2 ]

2 голосов
/ 19 августа 2010

Единственный раз, когда копируется ссылочный тип, это когда вы вызываете метод или свойство, которое активно делает копию. Clone () является очевидным примером (за некоторыми исключениями, с неизменяемым типом, таким как string, для Clone () безопасно просто возвращать тот же объект и делать вид, что он новый, так как ничего не может измениться).

as - это всегда личность. x = obj as T эквивалентно:

if(obj is T)
  x = (T)(object)obj;
else
  x = null;

Причина, по которой у меня есть (T)(object) вместо просто (T), заключается в том, что иногда существует неявный оператор приведения для приведения между двумя типами, и что может создать новый объект. Приведение к и из object не будет (если кто-то не был глуп с операторами приведения - я уверен, что компилятор остановит их, если они настолько глупы, но это настолько глупый случай, что я не могу потрудиться тестировать, не пишите приведения к объекту и обратно).

Если вы хотите проверить, совпадает ли объект с другим объектом, используйте ReferenceEquals, это сравнивается исключительно для идентичности, даже если Equals переопределено или аргументы являются типами значений в штучной упаковке.

0 голосов
/ 19 августа 2010
Ключевое слово

as никогда не создает новый объект (зачем это нужно?), Поэтому SomeProperty является новым объектом

(MySubClass)myInstance

myInstance as MySubClass

, это почти то же самое (и ни один не создаст новые экземпляры)не то же самое, если myInstance не является типом MySubclass, в этом случае первая строка выдаст исключение, а во второй строке оператор as вернет ноль)

...