Инициализация объекта и «Именом именованного конструктора» - PullRequest
1 голос
/ 07 марта 2009

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

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

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

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

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

РЕДАКТИРОВАТЬ: у меня нет простого способа изменить интерфейс MyType в настоящее время, поэтому добавление новых вызовов функций (хотя, вероятно, «лучший» подход) в настоящее время не очень практично.

Ответы [ 3 ]

2 голосов
/ 07 марта 2009

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

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

EDIT

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

1 голос
/ 07 марта 2009

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

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

Итак, вашим примером станет:

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

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

1 голос
/ 07 марта 2009

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

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