Как инициализировать структуру? - PullRequest
52 голосов
/ 12 декабря 2010

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

public struct MyStruct {
   String s;
   Int length;
}

MyStruct myStruct = new MyStruct { s = "Hello", length = 5 };

// Now, I want the following code to set the 's' to "Lol" and the
// length to 3 (length of "Lol"). The second part should be done
// automatically.
myStruct = "Lol"; // Or myStruct = String("Lol");

Как это сделать?

Ответы [ 4 ]

89 голосов
/ 12 декабря 2010

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

public struct MyStruct {
  public string s;
  public int length;

  public static implicit operator MyStruct(string value) {
    return new MyStruct() { s = value, length = value.Length };
  }

}

Пример:

MyStruct myStruct = "Lol";
Console.WriteLine(myStruct.s);
Console.WriteLine(myStruct.length);

Выход:

Lol
3
9 голосов
/ 19 марта 2013

Типы структур должны, когда это практически возможно, либо иметь все свои состояния, инкапсулированные в открытых полях, для которых могут быть независимо установлены любые значения, действительные для их соответствующего типа, либо вести себя как единое унифицированное значение, которое может быть установлено только черезконструктор, фабрика, метод или другое, передавая экземпляр структуры в качестве явного параметра ref одному из его открытых методов.Вопреки тому, что некоторые люди утверждают, что нет ничего плохого в структуре, имеющей открытые поля, если предполагается, что она представляет собой набор значений, которыми можно разумно манипулировать индивидуально или передавать в виде группы (например, координаты точки).Исторически существовали проблемы со структурами, которые имели установщики общедоступных свойств, и стремление избегать общедоступных полей (подразумевающее, что вместо них должны использоваться установщики) заставляло некоторых людей предлагать, что изменяемые структуры следует вообще избегать, но у полей нетпроблемы, которые свойства имели.Действительно, структура открытого поля является идеальным представлением для свободного набора независимых переменных, поскольку - это просто свободный набор переменных.

Однако в вашем конкретном примере это выглядитчто два поля вашей структуры, вероятно, не должны быть независимыми.Есть три способа, которыми ваша структура могла бы быть разумно разработана:

  • У вас могло бы быть единственное открытое поле, являющееся строкой, и затем было бы доступно только для чтения "вспомогательное" свойство, называемое length, котороесообщит о его длине, если строка не равна нулю, или вернет ноль, если строка будет иметь значение null.

  • Вы могли бы иметь структуру, не предоставляющую открытые поля, установщики свойств или методы мутации.и иметь содержимое единственного поля - частную строку - указывается в конструкторе объекта.Как и выше, length было бы свойством, которое сообщало бы о длине хранимой строки.

  • Вы могли бы сделать так, чтобы структура не открывала какие-либо открытые поля, установщики свойств или методы мутации,и имеют два приватных поля: одно для строки и одно для длины, оба из которых будут установлены в конструкторе, который принимает строку, сохраняет ее, измеряет ее длину и сохраняет ее.Определение длины строки достаточно быстрое, так что, вероятно, не стоит вычислять и кэшировать ее, но может быть полезно иметь структуру, объединяющую строку и ее значение GetHashCode.

Важно знать подробности, касающиеся третьего проекта, однако: если не поточно-безопасный код вызывает чтение одного экземпляра структуры во время записи в него другого потока, это может привести к случайному созданиюэкземпляра структуры, чьи значения полей несовместимы.Результирующее поведение может немного отличаться от поведения, которое возникает, когда классы используются без поточной безопасности.Любой код, имеющий отношение к безопасности, должен быть осторожен, чтобы не предполагать, что поля структуры будут в согласованном состоянии, поскольку вредоносный код - даже в среде с «полным доверием» - может легко генерировать структуры, состояние которых несовместимо, если это то, чтоон хочет это сделать.

PS - Если вы хотите, чтобы ваша структура была инициализирована с использованием присваивания из строки, я бы предложил использовать оператор неявного преобразования и сделать Lengthбыть доступным только для чтения свойством, которое возвращает длину базовой строки, если оно не равно нулю, или ноль, если строка является нулевой.

5 голосов
/ 12 декабря 2010
  1. Будет ли "длина" когда-либо отклоняться от реальной длины "s". Если ответ отрицательный, вам не нужно хранить длину, потому что строки уже хранят свою длину, и вы можете просто вызвать s.Length.

  2. Чтобы получить запрашиваемый синтаксис, вы можете реализовать «неявный» оператор, например, так:

    static implicit operator MyStruct(string s) {
        return new MyStruct(...);
    }
    
  3. Неявный оператор будет работать независимо от того, сделаете ли вы свою структуру изменчивой или нет.

1 голос
/ 12 декабря 2010

Ваша структура может иметь методы и свойства ... почему бы не попробовать

public struct MyStruct { 
    public string s;
    public int length { return s.Length; }
}

Исправление @ Ответ Гуффы показывает, что это возможно ... подробнее здесь: http://www.codeproject.com/KB/cs/Csharp_implicit_operator.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...