Проблемы с "где" в родовом наследовании

В следующем коде проблема на линии entities = doSpecialStuff(entities); потому что я "скучаю" по чему-то, где часть от моего doSpecialStuff() Methode

Error
The type 'T' cannot be used as type parameter 'T' in the generic type or method
'myWorkClass<T>.doSpecialStuff<T>(IEnumerable<T> entities)'. There is no implicit reference conversion from 'T' to 'ISpezial'.)

Код

вот моя структура наследования

public class Baseclass { }

public interface ISpezial 
{ 
    int mySpecial{get;set;} 
}

public class Class1 : Baseclass { }

public class Class2 : Baseclass, ISpezial
{
    public int mySpecial{ get;set;}
}

вот мой провайдер данных

public class myRepository
{
    public static IEnumerable<TResult> Load<TResult>() where TResult : Baseclass, new()
    {
        List<TResult> myEnum = new List<TResult>();

        if (typeof(ISpezial).IsAssignableFrom(typeof(TResult)))
        {
            myEnum.Add((new Class2() { mySpecial = 0 }) as TResult);
            myEnum.Add((new Class2() { mySpecial = 1 }) as TResult);
            myEnum.Add((new Class2() { mySpecial = 2 }) as TResult);
        }
        else
        {
            myEnum.Add((new Class1() as TResult));
            myEnum.Add((new Class1() as TResult));
            myEnum.Add((new Class1() as TResult));
        }

        return myEnum;
    }
}

и там это класс, который делает вещи и предоставляет ошибки, как босс

public class myWorkClass<T> where T : Baseclass, new()
{
    public void doNormalStuff()
    {
        var entities = myRepository.Load<T>();
        if (typeof(ISpezial).IsAssignableFrom(typeof(T)))
        {
            entities = doSpecialStuff(entities);
        }
    }

    public IEnumerable<T> doSpecialStuff<T>(IEnumerable<T> entities) where T : ISpezial
    {
        var list = new List<T>();

        return list.Where(special => special.mySpecial==2);
    }
}

еще один вопрос

Как я могу избежать new() по моему где?

и как я могу изменить добавить часть myRepository сделать myEnum.Add(new Class1()); вместо myEnum.Add((new Class1() as TResult)); без изменения возврата IEnumerable<TResult>?

1 ответ

Решение

Поскольку не существует неявного преобразования между T (Baseclass или потомком Baseclass), недостаточно проверить, присваивается ли ISpezial (что вы делаете, и это очень хорошо), вам также нужно явно приводить переменную при передаче ее как параметр, а затем приведите его обратно. Это действительно не лучший дизайн класса, все же.

 entities = doSpecialStuff(entities.Cast<ISpezial>()).Cast<T>();

2-й вопрос: поскольку вы явно вызываете конструкторы Class2() и Class1(), вы на самом деле не полагаетесь на полиморфизм / универсальную типизацию C#, поэтому существует ограничение new() (если вы написали new T(), например). Поэтому, пока вы сохраняете свой код таким образом, вы можете снять ограничение.

3-е: вы можете использовать ключевое слово Dynamics, составить список динамического типа и привести только в последний момент:

List<dynamic> myEnum = new List<dynamic>();
//your code
myEnum.Add((new Class2() { mySpecial = 0 })); //it's ok to write like you want it now
//your code
return myEnum.Cast<TResult>();
Другие вопросы по тегам