Подтвердить что ты не робот

Как инициализировать структуру?

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

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");

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

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

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

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

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

Ответ 3

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

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

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

Ответ 4

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

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

Коррекция. Ответ Guffa показывает, что это возможно... подробнее здесь: http://www.codeproject.com/KB/cs/Csharp_implicit_operator.aspx