Инициализация объекта и “Идиома именованного конструктора”

StackOverflow https://stackoverflow.com/questions/620484

  •  05-07-2019
  •  | 
  •  

Вопрос

ОК.Итак, у меня есть список значений, и я хотел бы сделать что-то вроде следующего:

MyObjectValues
.Select(currentItems=>new MyType()
{
     Parameter1 = currentItems.Value1,
     Parameter2 = currentItems.Value2
});

Итак, вот в чем проблема.Мне нужен приведенный выше пример для работы с именованными конструкторами, такими как:

MyObjectValues
.Select(currentItems=>MyType.GetNewInstance()
{
     Parameter1 = currentItems.Value1,
     Parameter2 = currentItems.Value2
});

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

Редактировать:В настоящее время у меня нет простого способа изменить интерфейс MyType, поэтому добавление новых вызовов функций (хотя, вероятно, это "лучший" подход) на данный момент не очень практично.

Это было полезно?

Решение

К сожалению, прямой поддержки этого в C # 3.0 нет.Инициализаторами объекта являются Только поддерживается для вызовов конструктора.Однако вы могли бы рассмотреть шаблон Builder.В моем порту буферов протокола я поддерживаю его следующим образом:

MyType foo = new MyType.Builder {Parameter1 = 10, Parameter2 = 20}.Build();

Таким образом, ваш пример стал бы:

MyObjectValues.Select(currentItems => new MyType.Builder
{
     Parameter1 = currentItems.Value1,
     Parameter2 = currentItems.Value2
}.Build());

Конечно, это означает написание вложенного типа Builder, но он может работать довольно хорошо.Если вы не возражаете, чтобы мой тип был строго говоря изменяемый, вы можете оставить неизменяемый API, но создать экземпляр Builder немедленно создайте новый экземпляр MyType, затем устанавливайте свойства по ходу работы (поскольку у него есть доступ к закрытым элементам), а затем, наконец, возвращайте экземпляр MyType в Build() способ.(Затем он должен "забыть" экземпляр, чтобы дальнейшая мутация была запрещена.)

Другие советы

Я уверен, что кто-нибудь придумает умный способ сделать это на C # до версии 4.0, но я только что прочитал Сообщение в блоге Сэма Нга об именованных параметрах в C # 4.0.Это должно решить вашу проблему.Это выглядело бы примерно так:

MyObjectValues.Select(currentItems=>MyType.GetNewInstance(
    Parameter1:currentItems.Value1,
    Parameter2:currentItems.Value2));

Редактировать

Не стоит упоминать, что делает это полезным то, что вы можете установить параметры по умолчанию, поэтому вам не нужно передавать их все.Запись в блоге - это хорошее краткое резюме.

Обновить: как насчет фабрики:

MyObjectValues.Select(currentItems=>MyTypeFactory.GetNewInstance(currentItems.Value1,
currentItems.Value2));


public static class MyTypeFactory
{
    public static MyType GetNewInstance(
         typeofvalue1 value1, 
         typeofvalue2 value2)
    {
        return new MyType { Parameter1 = value1, Parameter2 = value2 };
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top