Domanda

Hard to come up with a good title, but let's say I have this situation. I have a base class:

public abstract class FooBase
{

}

And I have a generic implementation:

public class MyFoo<T> : FooBase where T : Bar
{

}

So far so good. The abstract base is so I can create a heterogeneous collection of these generic items:

List<FooBase> list = new List<FooBase>()
{
    new MyFoo<Bar1>(),
    new MyFoo<Bar2>()
} 

Now the problem comes here. I have a generic method:

public void DoSomething<T>(MyFoo<T> aFoo) where T : Bar
{

}

And this works when I call it with an instance of a specific Foo:

DoSomething(new MyFoo<Bar1>());

But I want a function that will take a list and call DoSomething on each item:

public void DoSomethingWithList(List<FooBase> list) 
{
    foreach (var item in list) 
    {
        DoSomething(item);     // doesn't work - type cannot be inferred here
    }
}

So is there a way, at run-time to get it to figure out the correct type and call the generic function? Or is there some other way out of this conundrum?

È stato utile?

Soluzione

You can use dynamic typing - that will perform overload resolution at execution time with the actual type of the object that item refers to. You can simply change the iterator type to dynamic like this:

public void DoSomethingWithList(List<FooBase> list) 
{
    foreach (dynamic item in list) 
    {
        DoSomething(item);
    }
}

Note that if you end up with a FooBase in your list which isn't a MyFoo<T>, you'll get an execution time failure. You can avoid that (if you want) by providing another overload:

public void DoSomething(FooBase x)
{
    // This will be called for any items in the list that aren't
    // MyFoo<T>
}

Disadvantages of this approach:

  • It has some performance impact; whether that's significant or not will depend on your app, but you should test it.
  • You lose compile-time type safety.
  • It doesn't work before C# 4, which is when dynamic was introduced.

If you can avoid getting into this situation by redesigning a bit, that's often a good idea... but sometimes you really do need something like this.

Altri suggerimenti

Nope, since generic types have to be known in compile time, and your example does not provide information to the compiler, what type should he use, you have to manually insert type in method call

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top