C # Generics - вызов универсального метода из универсального класса - PullRequest
5 голосов
/ 02 февраля 2011

У меня есть следующие классы, и я пытаюсь вызвать метод Compare из класса ExportFileBaseBL, но получаю ошибку

Не удается неявно преобразовать тип 'Class1' в 'T'.Существует явное преобразование (вам не хватает приведения?)

public abstract class Class1<T> where T: Class2
{
    public abstract Class1<T> Compare(Class1<T> otherObj);
}

public abstract class Class3<T, U> where T: Class1<U>
                         where U: Class2
{
    public T Compare(T obj1, T obj2)
    {
        if (obj1.Prop1 > obj2.Prop1)
        {
            return obj1.Compare(obj2); // Compiler Error here
        }
        else
        {
            return obj2.Compare(obj1);  // Compiler Error here
        }
    }

}

Разве преобразование типов не должно быть неявным?Я что-то упустил?

Ответы [ 2 ]

4 голосов
/ 02 февраля 2011

Проблема в том, что ваш абстрактный метод Compare определен для принятия параметра типа Class1<T> и возврата экземпляра Class1<T>, , а не более конкретного типа, чем Class1<T>.Но это то, что пытается сделать ваш Class3.Compare метод: вызовите T.Compare и предположите, что результат будет T, хотя на самом деле вы можете быть уверены, что это будет Class1<U>.

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

class Parser
{
    public abstract object Parse(string text);
}

class Int32Parser
{
    public int Parse(Parser parser, string text)
    {
        return parser.Parse(text);
    }
}

Приведенный выше код делает ошибочное предположение похожим на ваше: что parser.Parse вернет int только потому, что1020 * происходит от object (как и в вашем случае, T должно происходить от Class1<U>);на самом деле, вы можете быть уверены, что он вернет object.

Существует два способа решения этой проблемы: сделать Class1<T>.Compare универсальным методом:

public abstract U Compare<U>(U otherObj) where U : Class1<T>;

... или ослабьте специфику типа возвращаемого значения вашего Class3.Compare метода:

public Class1<U> Compare(T obj1, T obj2)
{
    // ...
}

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

2 голосов
/ 02 февраля 2011

Вызовите метод с типом параметра, который вы объявили на уровне класса.

  return obj1.Compare<T>(obj2); 

Вам также понадобится сделать определение метода Compare общим:

public abstract Class1<T> Compare<T>(Class1<T> otherObj); 
...