1

in the following code is an problem on line entities = doSpecialStuff(entities); because i'm "missing" something in where part from my 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'.)

Code

here are my ineritance structure

public class Baseclass { }

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

public class Class1 : Baseclass { }

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

here is my data provider

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

and there it is the class who does stuff and provides errors like a boss

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

some further question

How can i avoid the new() in my where's?

and how can i change the Add part myRepository to do myEnum.Add(new Class1()); instead of myEnum.Add((new Class1() as TResult)); without changing the return IEnumerable<TResult>?

WiiMaxx
  • 5,322
  • 8
  • 51
  • 89

1 Answers1

2

Since there is no implicit conversion between T (Baseclass or child of Baseclass), it's not enough to check if ISpezial is assignable (which you do, and it's very good like that), you also need to explicitly cast the variable when passing it as a parameter, and then cast it back. It's really not the best class design, though.

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

2nd question: since you explicitly call Class2() and Class1() constructors, you're not really relying on the polymorphism/generic typing of C#, which is why the new() constraint is there (if you wrote new T(), for example). So as long as you keep your code like that, you can remove the constraint.

3rd: you can make use of the dynamics keyword, make your list of dynamic type, and cast only in the last moment:

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>();
Dragos Bobolea
  • 772
  • 7
  • 16
  • Not at all - unless you are working with literally millions of objects, case in which you'll lose a fraction of a second. Edit(wrong link before): see http://stackoverflow.com/questions/504729/how-do-i-cast-a-listt-effectively – Dragos Bobolea May 03 '13 at 08:31
  • 2
    ok after testing a bit with 10,000,000 objects agree with you :D – WiiMaxx May 03 '13 at 09:05
  • +1 for being pragmatic and actually testing it. Keep it up :D – Dragos Bobolea May 03 '13 at 09:06