2013-07-16 13 views
18

Mam wciąż wątpliwości dotyczące object. Jest to podstawowa klasa wszystkiego, każda klasa. Ale czy jest to typ odniesienia lub typ wartości. Lub, które z tych działań to? Muszę to wyjaśnić. Mam trudności ze zrozumieniem tego.Czy obiekt jest typem odniesienia lub typem wartości?

 object obj1 = "OldString"; 
    object obj2 = obj1; 
    obj1 = "NewString"; 
    MessageBox.Show(obj1 + " " + obj2); 
    //Output is "NewString OldString" 

W tym przypadku działa jak typ wartości. Jeśli obiekt był typ referencyjny to dlaczego wartość obj2 jest nadal „OldString”

class SampleClass 
    { 
     public string Text { get; set; } 
    } 

    SampleClass Sample1 = new SampleClass(); 
    Sample1.Text="OldText";   

    object refer1 = Sample1; 
    object refer2 = refer1; 

    Sample1.Text = "NewText"; 

    MessageBox.Show((refer1 as SampleClass).Text + (refer2 as SampleClass).Text); 
    //OutPut is "NewText NewText" 

W tym przypadku działa jak rodzaj odniesienia

Możemy wywnioskować, że typ object „s jest to, co w środku pola. Może to być zarówno typ referencyjny, jak i rodzaj wartości. Chodzi o to, co masz w środku. Czy mam rację?

Odpowiedz

22

To oznaczenie typu

Robi przykład z ciągiem jest bardzo świetlnej, ponieważ łańcuch jest również typu odniesienia (jak SampleClass oczywiście); twój przykład zawiera zero "boks".

jeśli obiekt jest typu odniesienie to dlaczego wartość obj2 jest nadal „OldString”

Dlaczego nie byłoby? Gdy tworzysz nowy ciąg nowy ciąg, to nie zmienia starych odniesień do punktu w nowym łańcuchu. Rozważmy:

 object obj1 = "OldString"; 
// create a new string; assign obj1 the reference to that new string "OldString" 

object obj2 = obj1; 
// copy the reference from obj1 and assign into obj2; obj2 now refers to 
// the same string instance 

obj1 = "NewString"; 
// create a new string and assign that new reference to obj1; note we haven't 
// changed obj2 - that still points to the original string, "OldString" 
+0

wykorzystujące ciąg jako przykład jest bardzo zły pomysł. ciąg jest odniesieniem, ale jest także niezmienny. Tworząc nowy, najpierw przegląda pulę łańcuchów, aby zobaczyć, czy taki ciąg już istnieje. string jest przypadkiem nadzwyczajnym, nie używaj go do wyjaśniania pojęć związanych z typami referencyjnymi i wartościowymi. – Markus

+0

"Kiedy tworzysz nowy, najpierw przegląda pulę napisów, aby sprawdzić, czy taki ciąg już istnieje." - to ... nie prawda. Sprawdzi to * w niektórych przypadkach *, ale nie w ogólnym przypadku. Co do tego, dlaczego użyłem napisu w pierwszej kolejności: * ponieważ pytanie dotyczyło właśnie łańcucha *. –

9

Kiedy robisz

obj1 = "NewString"; 

faktycznie posiada nowy odniesienie do innej lokalizacji w pamięci, a nie samą lokalizację, którą dał obj2 wcześniej. Gdy zmienisz treść lokalizacji obj1, otrzymasz tę samą zmianę w obj2.

Spróbuj zmienić zawartość obj1 z

fixed(char* c = obj1 as string) 
{ 
    c = '0'; 
} 

Oba swoimi strunami będzie teraz "0ldString".

Dzieje się tak, ponieważ obiekty są typami odniesienia.

+0

dziękuję za dokładniejsze pomógł – UfukSURMEN

7

Zmienna object jest zawsze referencyjnym typem.

Możliwe jest, aby object "odwoływał się" do typu wartości potęgą boksu. Pole to jest opakowaniem typu odniesienia o wartości, do której odnosi się zmienna object.

int x = 10;  // a value-type 
object o = x; 

zmiennej o jest odniesienie do pola zawierającego wartość x - ale nie x to:

x = 20; 
MessageBox.Show(string.Format("x:{0} o:{1}", x, o)); 

To może być bardziej pouczające o wartości typu zmienny:

struct SampleClass 
{ 
    public string Text { get; set }; 
    public override string ToString() { return Text; } 
} 

var x = new SampleClass{ Text = "Hello" }; 
object o = x; 
x.Text = "World"; 
MessageBox.Show(string.Format("{0} {1}", x, o)); 

o to pudełkowane odniesienie do x, więc zmiana x 's val ue nie ma wpływu na o.

Zmiana SampleClass na klasę zamiast ze struktury (typ referencyjny zamiast typu wartościowego) zmieniłaby zachowanie: linia object o = x; spowodowałaby, że odnosiłaby się do tej samej rzeczy co x, a zmiana tekstu x również by się zmieniła o tekst.

+0

dzięki za wyjaśnienie – UfukSURMEN

+0

bardzo dobrze wyjaśnił Steve. Więc w przypadku int tworzy wrapper. Jednak w przypadku struct jest to bezpośrednia konwersja do ref-type. Mam rację? Zastanawiam się tylko, dlaczego .NET framework nie stosuje tej samej techniki dla obu? Mam na myśli, dlaczego nie można przekonwertować int w ref-type lub dlaczego nie można przypisać struktury do niego przez wrapper? – Akie

0

Zmienna obiektowa jest zawsze typem odniesienia. Klasy i ciąg są typem odniesienia. Struct i enum są rodzajami wartości. Połączyłem duży przykład z różnych zasobów.

// PrintedPage is a value type 
//this is a struct 
struct PrintedPage 
{ 
    public string Text; 
} 

// WebPage is a reference type 
class WebPage 
{ 
    public string Text; 
} 

struct SampleClass 
{ 
    public string Text { get; set; } 
    public override string ToString() { return Text; } 
} 

void Main() 
{ 
     // First look at value type behaviour 
     PrintedPage originalPrintedPage = new PrintedPage(); 
     originalPrintedPage.Text = "Original printed text"; 

     // Copy all the information 
     PrintedPage copyOfPrintedPage = originalPrintedPage; 

     // Change the new copy 
     copyOfPrintedPage.Text = "Changed printed text"; 

     // Write out the contents of the original page. 
     // Output=Original printed text 
     Console.WriteLine ("originalPrintedPage={0}", 
          originalPrintedPage.Text); 


     //------------------------------------------------------------------- 
     // Now look at reference type behaviour 
     WebPage originalWebPage = new WebPage(); 
     originalWebPage.Text = "Original web text"; 

     // Copy just the URL 
     WebPage copyOfWebPage = originalWebPage; 
     // Change the page via the new copy of the URL 
     copyOfWebPage.Text = "Changed web text"; 

     // Write out the contents of the page 
     // Output=Changed web text 
     Console.WriteLine ("originalWebPage={0}", 
          originalWebPage.Text); 

     // Now change the copied URL variable to look at 
     // a different web page completely 
     copyOfWebPage = new WebPage(); 
     copyOfWebPage.Text = "Changed web page again"; 

     Console.WriteLine ("originalWebPage={0}", 
          originalWebPage.Text); 
     Console.WriteLine ("copyOfWebPage={0}", 
          copyOfWebPage.Text); 


     //------------------------------------------------------------------- 
     //string are reference type too 
     object obj1 = "OriginalString"; // create a new string; assign obj1 the reference to that new string "OriginalString" 
     object obj2 = obj1;// copy the reference from obj1 and assign into obj2; obj2 now refers to // the same string instance 
     obj1 = "NotOriginalString";// create a new string and assign that new reference to obj1; note we haven't // changed obj2 - that still points to the original string, "OriginalString" 
     /* When you do obj1 = "NewString"; it actually holds a new reference, to another memory location, not the same location you gave to obj2 before. 
      IMP - When you change the content of the location obj1, you will get the same change in obj2. 
     */ 
     Console.WriteLine(obj1 + " " + obj2); 

     //------------------------------------------------------------------- 
     object onj11 = 2; 
     object obj12 = onj11; 
     onj11 = 3; //you assigned boj11 to a new reference but obj12 reference did not change 
     Console.WriteLine(onj11 + " " + obj12); 

     //-------------------------------------------------------------------  
     /*look below - it's possible for object to "reference" a value-type by the power of boxing. The box is a reference-type wrapper around a value, to which the object variable refers.*/ 
     int i = 2; //int is value type 
     object j = i; //variable j is a reference to a box containing the value of i- but it's not i 
     i = 3; 
     Console.WriteLine(i + " " + j);  

     //------------------------------------------------------------------- 
     var x = new SampleClass{ Text = "Hello" }; 
     object o = x; 
     x.Text = "World"; 
     Console.WriteLine(x.Text + " " + o); 

     //------------------------------------------------------------------- 
     SampleClass x1 = new SampleClass{ Text = "Hello" }; //sample class is of type struct which is value type; it is was of type class then the data would be copied over and result would be World World 
     SampleClass o1 = x1; 
     o1.Text = "World"; 
     Console.WriteLine(x + " " + o); 
    } 

Referencje - http://jonskeet.uk/csharp/references.html

+0

Dzięki za wyjaśnienie. to naprawdę pouczające – UfukSURMEN

Powiązane problemy