Метод C # Struct не сохраняет значение, если к нему обращается свойство - PullRequest
3 голосов
/ 21 июля 2011

Мне нужно создать структуру, которая выглядит как int (но имеет дополнительное поле, которое мне нужно ...), поэтому я создал новую структуру с именем TestStruct, добавил один метод (test ()), который мне был нужен, и перегрузил некоторые операторы, и это, кажется, работает хорошо ...

Пример ниже показывает проблему. Если метод struct test () выполняется из свойства Val, то свойство Val, похоже, теряет значение, но если метод выполняется для переменной Val2, этот, похоже, сохраняет правильное значение ...

Почему это происходит?

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        new TestClass();
    }
}

public class TestClass
{
    public TestStruct Val { get; set; }
    private TestStruct Val2;

    public TestClass()
    {
        Val.test();
        Console.WriteLine(Val + "-> why is it not 10?");

        //Direct assignment works well...
        Val = 123;
        Console.WriteLine(Val  + "-> direct assingment works..");

        //This way works too. Why doesn't it work with "get;" and "set;"?
        Val2.test();
        Console.WriteLine(Val2 + "-> it works this way");
    }
}

public struct TestStruct
{
    private Int32 _Value;
    public long Offset { get; set; }

    public static implicit operator TestStruct(Int32 value)
    {
        return new TestStruct { _Value = value };
    }

    public static implicit operator Int32(TestStruct value)
    {
        return value._Value;
    }

    public void test()
    {
        _Value = 10;
    }
}

Ответы [ 4 ]

11 голосов
/ 21 июля 2011

Ваш struct неверен.

По очень большому количеству причин вы должны никогда создать изменяемую структуру.

Так же, как intили DateTime значение является неизменным и никогда не может изменяться, поэтому слишком конкретное значение вашего struct никогда не должно изменяться вообще.

Вместо этого вы можете создавать функции, которые возвращают новое, другое значение.

Вот несколько причин, по которым изменчивые структуры являются злом:

  1. http://ericlippert.com/2008/05/14/mutating-readonly-structs/
  2. http://blog.slaks.net/2010/12/when-shouldnt-you-write-ref-this.html
  3. http://codeblog.jonskeet.uk/2010/07/27/iterate-damn-you/
  4. http://philosopherdeveloper.wordpress.com/2011/03/31/how-i-discovered-a-bug-in-the-c-compiler-part-1/

Чтобы ответить на вопрос, Val.test() эквивалентно get_Val().test().
Поскольку структуры являются типами значений, `get_Val () (автоматически генерируемый метод получения свойства) возвращает копию структуры.
Исходная структура в частном вспомогательном поле не затрагивается.

8 голосов
/ 21 июля 2011

Это структура, так что это тип значения - он копируется по значению, а не по ссылке.

Свойства - это просто синтаксический сахар вокруг вызовов методов, Val компилируется в следующее:

private TestStruct _valBackingField;
public TestStruct get_Val {
    return _valBackingField;
}

При доступе к структуре через свойство вы получаете свежую копию каждый раз, когда получаете доступ к Геттеру. Получая доступ к структуре через поле, вы каждый раз получаете один и тот же объект.

Вот почему изменяемые типы значений считаются злыми.

1 голос
/ 21 июля 2011

Когда вы используете Val, свойство возвращает копию, именно эту копию вы изменяете, а затем вы снова получаете доступ к свойству, которое получает другую копию.

Если вы измените структуру на класс, эта проблема должна исчезнуть, потому что если разница в способах обработки классов и структур.

0 голосов
/ 21 июля 2011

После прочтения некоторых ссылок я понимаю проблему ..

Я исправил это, изменив метод test(), чтобы он возвращал новую структуру с новым значением, а затем вместо Val.test() Ido Val = Val.test();.

Я думаю, что похожая ситуация возникает, когда мы хотим заменить некоторые символы в строке, мы должны сделать что-то вроде str = str.replace("xx","yy");

Спасибо всем за помощь.Я не ожидал получить все эти ответы так быстро

...