2

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

2
  • Is mygen supposed to be template? Commented Aug 24, 2010 at 18:04
  • Im confused as to the signature of bang, are you trying to say that it accepts an arbitrary class? Commented Aug 24, 2010 at 18:10

4 Answers 4

2

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.

Sign up to request clarification or add additional context in comments.

6 Comments

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.
+1, nice explanation of why there's no automatic covariance on generic types.
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.
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.
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.
|
1

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

1 Comment

I basically implemented what chilltemp demonstrated. I appreciate Andorbal's suggestions and recursive first answer and his comment that Cast would avoid the lambda.
1

It should be, and is in .Net 4.0.

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

Comments

0

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.

1 Comment

If you use .Cast instead of Select, you don't need to pass a lambda.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.