Вызовите неуниверсальный метод (Generic <Base>[] args) и передать массив Generic <Derived>? - PullRequest
0 голосов
/ 07 июля 2011

Решение для вызова неуниверсального метода и передачи универсальных аргументов с различными универсальными типами?

Мой воображаемый сон:

void FooBulous(Foo<object>[] fooArray) {  } // Accept any 'Foo<BaseType>'

var fooArray = new Foo<object>[]    // Array of 'Foo<BaseType>'
{
  new Foo<Cat>(),
  new Foo<Dog>(),
};

FooBulous(fooArray); // Pass the 'Foo<BaseType>[]' array

Моя реальность:

void BarBaric(object[] barArray) {  } // Can't constrain to 'Foo<>'

var barArray = new object[]  // Same problem
{
  new Bar<Cat>(),
  new Bar<Dog>(),
};

BarBaric(barArray); // Barbaric! I thought the 'void *ptr' days were over!

В итоге:

void Fee(object[] params)      { /* WORKS! But not constrained to 'Foo<Base>' */ }
void Fie(Foo<Cat>[] params)    { /* Does not accept 'Foo<Dog>' */ }
void Foe(Foo<>[] params)       { /* ERROR: 'Type expected' */ }
void Fum(Foo<object>[] params) { /* Cannot convert 'Foo<Cat>' to 'Foo<object>' */ }

Очевидно, что это невозможно сделать ... Есть ли чистая альтернатива?

1 Ответ

5 голосов
/ 07 июля 2011

Проблема в том, что Foo<Cat> не Foo<object>.Предположим, что Foo выглядит следующим образом:

public class Foo<T>
{
    public void Method(T input)
    {
        ...
    }
}

Тогда Foo<Cat> всегда будет ожидать, что значение Cat для параметра input будет Method.Но если бы вы могли трактовать Foo<Cat> как Foo<object>, вы могли бы сделать:

Foo<Cat> catFoo = new Foo<Cat>();
Foo<object> objectFoo = catFoo;
objectFoo.Method(new object()); // Eek! Type safety is broken!

Теперь универсальная дисперсия доступна в .NET 4 (и C # 4), но только для интерфейсов и делегатов и только для тех, кто оформлен с соответствующими out и in в точке объявления параметра типа.Это может или не может быть полезным для вас.

Другой вариант - сделать Foo<T> производным от абстрактного неуниверсального базового класса Foo, который предоставляет все члены, которые не имеют ничего общего с T,Тогда вы можете написать:

void Foobulous(Foo[] fooArray)

...

Foobulous(new Foo[] {
    new Foo<object>(),
    new Foo<Cat>(),
    new Foo<Dog>()
});

и все будет хорошо, если Foobulous не нужно использовать ни один из методов, основанных на T - чего не следует, учитываячто он может принимать Foo значения с параметрами другого типа в любом случае.

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