Kiedy kopiowana jest wartość / obiekt C# i kiedy kopiowana jest jego Referencja?

Ciągle mam ten sam problem, gdzie kopiowany jest obiekt, do którego chcę się odwoływać, lub w którym odwołuje się obiekt, do którego chcę się odwoływać. Dzieje się tak, gdy używam operatora=.

Na przykład, jeśli wysyłam obiekt do innego formularza, czyli:

SomeForm myForm = new SomeForm();
SomeObject myObject = new SomeObject();
myForm.formObject = myObject;

...a następnie zmodyfikować obiekt w formie, oryginalny obiekt nie zostanie zmodyfikowany. To tak, jakby obiekt został skopiowany, a nie odwołany. Ale kiedy to robię:

SomeObject myObject = new SomeObject();
SomeObject anotherObject = new SomeObject();
anotherObject = myObject;

...a następnie zmodyfikować anotherObject, myObject zostaje również zmodyfikowany.

Najbardziej obciążający przypadek jest wtedy, gdy próbuję sklonować jeden z moich zdefiniowanych obiektów:

public class SomeObject
{
    double value1, value2;

    //default constructor here

    public SomeObject(val1, val2)
    {
        value1 = val1;
        value2 = val2;
    }

    public void Clone(SomeObject thingToCopy)
    {
        this.value1 = thingToCopy.value1;
        this.value2 = thingToCopy.value2;
    }
}
Kiedy to zrobię...
SomeObject obj1 = new SomeObject(1, 2);
SomeObject obj2 = new SomeObject();
obj2.Clone(obj1);

...obj1 jest odwołany i wszelkie modyfikacje obj2 zmiany obj1.

Obiekty systemowe, takie jak int, double, string, etc wydają się być zawsze kopiowane, z wyjątkiem przypadku metody klonowania powyżej.

Moje pytanie brzmi, nie biorąc pod uwagę użycia słowa kluczowego ref w funkcjach, kiedy obiekt zostanie skopiowany i kiedy obiekt jest odwoływany w każdym przypadku (np. podczas przechodzenia do funkcji, podczas ustawiania jako inne obiekty (jak dwa pierwsze powyższe przykłady), podczas kopiowania zmiennych członkowskich, takich jak trzeci przykład, itd.)?

Author: BJ Myers, 2010-12-03

3 answers

Trudno jest dokładnie odpowiedzieć na takie pytanie, nie poświęcając dużo czasu na uważne dobieranie słów.

Zrobiłem to w kilku artykułach, które mogą okazać się przydatne:

To nie znaczy, że artykuły są doskonałe, oczywiście-dalekie od tego - ale starałem się być tak jasny, jak Mogę.

Myślę, że jeden ważny chodzi o to, aby oddzielić dwie koncepcje (przekazywanie parametrów i typy odniesienia vs wartości) w twojej głowie.

Aby spojrzeć na konkretne przykłady:

SomeForm myForm = new SomeForm();
SomeObject myObject = new SomeObject();
myForm.formObject = myObject;

Oznacza to, że myForm.formObject i myObject odnoszą się do tej samej instancji SomeObject - Jak dwie osoby posiadające oddzielne kartki papieru, z których każda ma ten sam adres wypisany na nich. Jeśli pójdziesz do adresu na jednym kawałku papieru i pomalować dom na czerwono, a następnie przejdź do adresu na drugim kawałku papieru, zobaczysz czerwony house.

Nie jest jasne, co masz na myśli przez "a następnie zmodyfikuj obiekt w formie", ponieważ typ, który podałeś, jest niezmienny. Nie ma możliwości modyfikacji samego obiektu. Możesz zmienić myForm.formObject, aby odnosić się do innej instancji SomeObject, ale to tak, jakbyś zapisał adres na jednej kartce papieru i zamiast tego napisał na niej inny adres. To nie zmieni tego, co jest napisane na drugiej kartce papieru.

Jeśli mógłbyś podać krótki, alekompletny program którego zachowania nie rozumiesz (najlepiej aplikacja konsolowa, żeby wszystko było krótsze i prostsze) łatwiej byłoby mówić o konkretnych rzeczach.

 38
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-03 17:22:27

Hi Mike Wszystkie obiekty, które pochodzą z ValueType, takie jak struct lub inne prymitywne typy, są typami wartości. Oznacza to, że są one kopiowane za każdym razem, gdy przypisujesz je do zmiennej lub przekazujesz jako parametr metody. Inne typy są typami odniesienia, co oznacza, że gdy przypisujesz Typ odniesienia do zmiennej, nie jej wartość, ale jej adres w przestrzeni pamięci jest przypisany do zmiennej. Należy również zauważyć, że można przekazać typ wartości jako odniesienie za pomocą słowa kluczowego ref. Oto składnia

public void MyMethod(ref int a) { a = 25 }
int i = 20;
MyMethod(ref i); //Now i get's updated to 25.

Mam nadzieję, że pomoże:)

 4
Author: Davita,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-03 17:03:44

W odniesieniu do klonowania obiektów jeśli wartości kopiowane z jednego obiektu do drugiego są typami odniesienia, to wszelkie modyfikacje tych wartości w oryginalnym obiekcie będą miały wpływ na wartości w skopiowanym obiekcie (ponieważ są tylko odniesieniami do tego samego obiektu)

Jeśli chcesz sklonować obiekt, który ma właściwości, które są typami referencyjnymi, musisz albo uczynić te typy klonowalnymi, albo wykonać ich ręczną kopię, tworząc nowe instancje jako wymagane.

Conside przy użyciu interfejsu IClonable choć nie jest to najlepsze rozwiązanie imho.

 1
Author: RobV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-03 17:04:38