views:

87

answers:

4

This is a rather elementary C# question; my apologies, but I haven't been able to find this elsewhere.

What is the best way to convert from Object<class> to Object<interface>?

I.e.

//fake interface
interface ignu {}

//fake class which implements fake interface
class bee : ignu {}

//function which accepts a generic with the interface
function bang(template<bee>) {}

//template type but with a class that implements the interface
template<bar> foo;

//trying to call the function, but compiler complains it can't implicitly convert
bang(foo); 

//compilers complains that it cannot convert from template<bee> to template<ignu>
bang((template<ignu>)bee)

Maybe I'm way off base, but this seems like it should work and be doable, but the solution is escaping me.

Edit: Changed mygen to be template as I was using both to refer to the same thing which was confusing

Edit: I ended up using a Cast similar to: bang(bee.Cast());

+1  A: 

It should be, and is in .Net 4.0.

Check this out: http://msdn.microsoft.com/en-us/library/dd799517.aspx

MonkeyWrench
+2  A: 

There is no guarantee that Generic<SubType> can actually be used as a replacement for Generic<BaseType>.

Consider this:

List<int> intlist = new List<int>();
List<object> objlist = intlist; // compile error
objlist.Add("foo"); // what should be in intlist now?

What you are looking for is called co- and contra- variance. They have been added in c#4.

recursive
You're sending a double message. The example you give (which is similar to the question's) won't work in 4.0 either. And it should not.
jdv
+1, nice explanation of why there's no automatic covariance on generic types.
Heinzi
You've highlighted a problem with inheritance in object oriented programming; is that really a valid argument when it comes to interfaces though? Isn't the point of an interface to standardize some actions you may take between peer classes? Is it really unreasonable to say I want to do it on a collection of such classes instead of just one instance? These are honest questions btw; I see from answer below I can get around it, so I'm looking for some of the should I and what caveats should I look out for.
William
Classes that implement an interface are not interchangable. In other words, a class can implement an interface, plus other methods besides. In order for the code I posted to work, the two types would have to be implicitly convertible to each other, in both directions.As jdv points out, generic variance only works in c#4, and only then when it is explicitly specified on the types in question.
recursive
Classes that implement an interface are not interchangable; but if sticking to the methods in the interface (which the compiler should enforce if its accepting types of the interface), then I would (possibly naively) assume that's safe.Now in the case of a collection of interfaces, there are potential issues if you add objects. If the collection is immutable (at least in the scope of it being cast as an interface), then I should be okay, correct?I'm actually looking at using collections of the interface in a view of the MVC so I think I'm safe.
William
Yes, I think that's ok. IEnumerable<T> is covariant (meaning the conversion is automatic) in .net 4.0 for that reason.
recursive
A: 

In .NET 3.5, I would handle something like this in a list like the following:

list<bar> myList = new list<bar>;
myList.Select<ignu>(x => x).ToList();

I would think it wouldn't be too hard to do something like that for a single object.

Andorbal
If you use .Cast instead of Select, you don't need to pass a lambda.
recursive
That's even better!
Andorbal
+1  A: 

.NET 3.5 doesn't have Covariance and Contravariance in Generics as MonkeyWrench indicated. However, there are built in ways to do the casting necessary.

class Program
{
    static void Main(string[] args)
    {
        List<ccc> c = new List<ccc>();
        c.Add(new ccc());

        List<iii> i = new List<iii>(c.Cast<iii>());
    }
}

interface iii
{
    void DoIt();
}

class ccc : iii
{
    public void DoIt()
    {
        throw new NotImplementedException();
    }
}
chilltemp
I basically implemented what chilltemp demonstrated. I appreciate Andorbal's suggestions and recursive first answer and his comment that Cast would avoid the lambda.
William