2009-09-09 3 views
6

В соответствии с MSDN (раздел 11.3.6 на C# spec):Значение "этого" для структуры (C#)

внутри экземпляра конструктору структуры, this соответствует out параметра тип структуры и в элементе функции экземпляра a struct, this соответствует параметру типа структуры типа ref . В обеих случаях , this классифицируются как переменными, а можно изменить всю структуру, для которой член функции был вызван с помощью присвоения this или пропускания this в качестве параметра ref или out.

Я не понимаю. Как this отличается от структуры, чем для класса? Примеры кода оцениваются

ответ

11

У Эрика Липперта был потрясающий post на мутации readonly struct, а затем назад, что действительно поможет прояснить проблему для вас. Там даже пример кода и викторина!

Главной точкой является то, что struct s соответствует смысловой семантике и class es нет, и поэтому this должен означать что-то другое для этих двух. this - readonly для class, но не для struct. Следующий код является законным

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; 
    } 
} 

, но не тогда, когда «struct» заменяется на «class

6

Когда вы имеете дело со структурами, вы имеете дело со значениями.

В классе «это» является ссылкой на текущий экземпляр. Это позволяет вам мутировать экземпляр класса, задав свойства/поля в классе.

Однако, если вы находитесь в структуре, все действует по-другому. Когда вы находитесь в методе struct, «this» позволяет вам мутировать структуру. Однако, если вы используете это в методе, вы почти всегда имеете дело с копией «оригинальной» структуры.

Например:

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

При использовании этого:

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 
} 

Теперь незнакомец часть - это справедливо, и что это цитата говорит:

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

Ответ Джейсона и сообщение Эрика показывают один аспект this, который интересен ... но есть еще один, который еще более тревожно:

Вы можете переназначить this в пределах метода, даже если этот тип является неизменным.

Чтобы продемонстрировать это, мы будем использовать на структуру, которая хранится в не-только для чтения переменной, но содержит поле только для чтения:

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

Я чувствовал большое волнение в Силе, так как если миллионы голосов внезапно закричали в ужасе и призывали к состязательности. Пожалуйста, не показывайте это моим сотрудникам на C++. :-) –

+1

Eh, const в C++ - это ложь. В C++ const часто означает «я обещаю не изменять эту вещь», а не «у меня есть гарантия, что эта вещь неизменна». –

+0

Хороший пример Jon. Здесь вы демонстрируете, что хотя структура может быть неизменной, переменная *, которая содержит структуру, не является. Эта переменная может по-прежнему меняться; поэтому его называют переменной. Это просто ужасный способ сделать его разным. –

Смежные вопросы