0

I have an Array of Interfaces to ObservableCollection-s of different, related types:

public IObsColD[] dsLists = new IObsColD[]
            {
                 new ObsColD<DSection>(),
                 new ObsColD<DSection4>(),
                 new ObsColD<DSection5>()
            };  
public interface IObsColD { }
public class ObsColD<T> : ObservableCollection<T>, IObsColD where T : new()
{
    public ObsColD() { }
    public ObsColD(int n = 0)
    {
        for (int i = 0; i < n; i++)
            this.Add(new T());
    }
}

then somewhere in the program I assign dsLists[2] (an ObservableCollection of DSection5 type variables) to a parameter p, use p as an argument to function f and in f I try to do a foreach.

But then I need to know p's Type for re-casting. Or: I need to know if the ObsCol is a Collection of DSection5 or of DSection4 type variables.

How do I find out the type of p's Items at that moment?

Erik
  • 894
  • 1
  • 8
  • 25
  • Please post your code, not a description of your code. – nvoigt May 17 '15 at 11:52
  • @Erik You can do it with a bit of Reflection, but are you sure that such upcasting-downcasting is what you really need to solve [the problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)? You should strive to avoid casting whenever possible, replacing it with some form of virtual dispatch like virtual methods or(and) [visitor pattern](http://stackoverflow.com/questions/9818132/difference-betwen-visitor-pattern-double-dispatch). Only when virtual dispatch is not an option, casting shall be used. – Eugene Podskal May 17 '15 at 12:32

2 Answers2

0

Your p is of type IObsColD, not ObservableCollection, therefore a foreach will only work if your interface implements IEnumerable.

If your DSection classes have a common base class or interface, you could have IObsColD implement IEnumerable<DSectionBase> and work from there.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
  • Some DSectionx classes have base class A and some have B. Both A and B have a common base class Section that has the properties i need to process. – Erik May 17 '15 at 13:50
  • Then use it. Have `IObsColD` implement `IEnumerable
    ` and you are good to go.
    – nvoigt May 17 '15 at 13:54
0

The is keyword and the as keyword should be of some help.

This is some sample implementation that checks whether the argument passed to the f method is ObsColD<DSection5> or ObsColD<DSection4>. When that's checked you can safely cast the col parameter to appropriate collection.

public void MyMethod()
{
    var p = this.dsLists[2];
    this.f(p);
}

private void f(IObsColD col)
{
    if (col is ObsColD<DSection5>)
    {
        foreach (var item in (ObsColD<DSection5>)col)
        {

        }
    }
    else if (col is ObsColD<DSection4>)
    {
        foreach (var item in (ObsColD<DSection4>)col)
        {

        }
    }
}

And implementation using as: cast using the keyword. If the cast is incorrect it will result in null otherwise it's cast to expected type. Then check for null:

private void f(IObsColD col)
{
    var ds5 = col as ObsColD<DSection5>;
    var ds4 = col as ObsColD<DSection4>;

    if (ds5 != null)
    {
        foreach (var item in ds5)
        {

        }
    }
    else if (ds4 != null)
    {
        foreach (var item in ds4)
        {

        }
    }
}
PiotrWolkowski
  • 8,408
  • 6
  • 48
  • 68