Шаблоны C # и специальные конструкторы - PullRequest
1 голос
/ 04 февраля 2009

У меня есть набор некоторых классов, которые все могут быть построены с аргументом, являющимся экземпляром определенного интерфейса. Поскольку все они могут быть созданы одним и тем же объектом (и процесс, во время которого происходит это построение, во многом одинаков), я подумал, что, возможно, будет работать шаблон. По сути, я хочу сделать что-то вроде этого:

public static void dostuff<T, U> (List<T> items)
{
    foreach (T item in items)
    {
        func(new U(item).SpecialMember);
    }
}

Конечно, это не скомпилируется, так как U шаблонизирован и поэтому не имеет SpecialMember, а также конструктора T.

В принципе, любая данная реализация интерфейса T имеет определенные особенности. U является реализацией T which has an additional feature that is needed *and* which can be constructed from an any instance of U`.

Рекомендации

Ответы [ 5 ]

4 голосов
/ 04 февраля 2009

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

Лично я хотел бы увидеть это изменение, используя идею "статические интерфейсы" (применимо только для ограничений типов), но на данный момент лучшее, что вы получите, это фабрика типов или отражение - или, возможно, конструктор без параметров и метод "Init" в интерфейсе. Честно говоря, ни один из них не является хорошим вариантом.

2 голосов
/ 04 февраля 2009

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

public class SpecialObjFactory<T,U> where T : ISpecialMethod
where u : new()
{
}
0 голосов
/ 29 апреля 2009
public static void dostuff<T, U> (List<T> items)
{
    foreach (T item in items)
    {
        U obj = ( U )System.Activator.CreateInstance( typeof( U ), item );
        func(obj.SpecialMember);
    }
}
0 голосов
/ 04 февраля 2009

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

public static void dostuff<T, U> (List<T> items) where T : SomeClass where U : SomethingElse
{
}

Но это позволит вам получить доступ только к членам этих классов / интерфейсов, а не к конструкторам.

Чтобы расширить ответ Джоэла, вы должны добавить метод к интерфейсу T (в моем примере SomeClass), который принимает объект T и возвращает новый объект U. Примерно так:

public class SomeClass    
{
    CreateInstanceOfSomethingElse() { return new SomethingElse(this); }
}

public static void dostuff<T, U> (List<T> items) where T : SomeClass, U : SomethingElse
{
    foreach (T item in items)
    {
        func(item.CreateInstanceOfSomethingElse().SpecialMember);
    }

}

В качестве другого совершенно другого подхода вы можете указать, что метод doStuff также принимает Func<T, U>, который должен создавать U из объекта T.

public static void dostuff<T, U> (List<T> items, Func<T, U> createU)
{
    foreach (T item in items)
    {
        func(createU(item).SpecialMember);
    }

}

Это запутывается, если создание вашего объекта является чем-то более сложным, чем простая ламба, подобная

t => new U(t)

0 голосов
/ 04 февраля 2009

Вы хотите шаблон Factory . Добавьте фабричный метод к вашему интерфейсу T, который возвращает типы U.

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