2009-09-09 12 views
6

Según MSDN (Sección 11.3.6 de la C# spec):Significado de "este" para un struct (C#)

dentro de una instancia constructor de un struct , this corresponde a un parámetro de out el tipo de estructura, y dentro de un miembro de función de instancia de a struct, this corresponde a un ref parámetro del tipo de estructura. En ambos casos , this se clasifica como una variable , y es posible modificar toda la struct para el cual el miembro de función fue invocado por asignando a this o pasando this como un parámetro ref o out.

No lo entiendo. ¿Cómo es this diferente para una estructura que para una clase? Los ejemplos de código son apreciados

Respuesta

11

Eric Lippert tuvo un fabuloso post en la mutación readonly struct s hace un tiempo que realmente ayudará a aclarar el problema para usted. ¡Incluso hay un ejemplo de código y un cuestionario!

El punto sobresaliente es que struct s semántica de valor obedecer y no es class y así this no deben significar algo diferente para los dos. this es readonly para class, pero no para struct. El siguiente código es legal

struct Point { 
    public int x; 
    public int y; 

    public Point(int x, int y) { 
     this.x = x; 
     this.y = y; 
    } 

    public void DoGoTime() { 
     GoTime(ref this); 
    } 

    public static void GoTime(ref Point p) { 
     p.x = 100; 
     p.y = 100; 
    } 
} 

pero no es si "struct" se sustituye por "class."

6

Cuando se trata de estructuras, se trata de tipos de valores.

En una clase, "esto" es una referencia a la instancia actual. Esto le permite mutar la instancia de clase estableciendo propiedades/campos en la clase.

Sin embargo, si estás en una estructura, las cosas actúan de manera diferente. Cuando estás en el método de una estructura, "esto" te permite mutar la estructura. Sin embargo, si estás usando esto en un método, casi siempre estás tratando con una copia de la estructura "original".

Por ejemplo:

struct Test 
{ 
    int i; 
    void Mutate() { 
     this.i += 1; 
    } 
} 

Cuando se utiliza esta:

void MutateTest(Test instance) 
{ 
    instance.Mutate(); 
} 

{ 
    Test test = new Test(); 
    test.i = 3; 
    Console.WriteLine(test.i); // Writes 3 
    test.Mutate(); // test.i is now 4 
    Console.WriteLine(test.i); // Writes 4 
    MutateTest(test); // MutateTest works on a copy.. "this" is only part of the copy itself 
    Console.WriteLine(test.i); // Writes 4 still 
} 

Ahora, la parte desconocido - esto es válido, y lo que esa cita estaba diciendo:

struct Test 
{ 
    public Test(int value) 
    { 
     this.i = value; 
    } 
    int i; 

    void Mutate(int newValue) { 
     this = new Test(newValue); // This wouldn't work with classes 
    } 
} 


/// 
{ 
    Test test = new Test(); 
    test.i = 3; 
    Console.WriteLine(test.i); // Writes 3 
    test.Mutate(4); 
    Console.WriteLine(test.i); // Writes 4 
6

La respuesta de Jason y la de Eric muestran un aspecto de this que es interesante ... pero hay otro que es aún más alarmante:

Puede reasignar this dentro de un método, incluso si el tipo es inmutable.

Para demostrarlo, vamos a utilizar una estructura que se almacena en un no-sólo lectura variables , pero que contiene un campo de sólo lectura:

using System; 

public struct LooksImmutable 
{ 
    private readonly int value; 
    public int Value { get { return value; } } 

    public LooksImmutable(int value) 
    { 
     this.value = value; 
    } 

    public void GoCrazy() 
    { 
     this = new LooksImmutable(value + 1); 
    } 
} 

public class Test 
{ 
    static void Main() 
    { 
     LooksImmutable x = new LooksImmutable(5); 
     Console.WriteLine(x.Value); 
     x.GoCrazy(); 
     Console.WriteLine(x.Value); 
    } 
} 
+0

me sentí una gran perturbación en la Fuerza, como si millones de voces gritaban aterrorizadas y pedían una const corrección. Por favor, no mostrar esto a mis compañeros de trabajo de C++. :-) –

+1

Eh, const en C++ es una mentira. En C++, const significa a menudo "Prometo no cambiar esta cosa", y no "tengo la garantía de que esto sea inmutable". –

+0

Buen ejemplo Jon. Aquí lo que está demostrando es que aunque la estructura puede ser inmutable, la * variable * que contiene la estructura no lo es. Esa variable aún puede variar; es por eso que se llama una variable. Esta es solo una manera particularmente horrible de hacer que varíe. –