Question

I prepared a sample application of a problem I have in a big WPF application.

The issue I have is with upcasting the second type of the TreeColumn instance obsTreeColumn to a Collection. As you can see when I do this with just one type the upcast works fine. The method DoSomethingWithColumn needs to be able to work with any type of collection as the second generic type of the parameter collection.

public class TreeColumn<T, TValue>  where TValue : Collection<T> {
    // A lot happens in here...
}

public class Data {
    public int Id { get; set; }
    public int Code { get; set; }
    // And much more...
}

class Program {
    static void Main(string[] args) {
        var expander = new TreeExpander<Data>();
        var obsTreeColumn = new TreeColumn<Data, ObservableCollection<Data>>();
        var colTreeColumn = new TreeColumn<Data, Collection<Data>>();

        var obsCollection = new ObservableCollection<Data>();
        var colCollection = new Collection<Data>();

        expander.DoSomethingWithColumn(obsTreeColumn);
        expander.DoSomethingWithColumn(colTreeColumn);
        expander.DoSomethingWithCollection(obsCollection);
        expander.DoSomethingWithCollection(colCollection);
        Console.ReadKey();
    }
}

class TreeExpander<T> where T : class {

    private int _rowCounter;

    public void DoSomethingWithColumn(object column) {

        // WHY ISN'T THIS CAST WORKING WITH A TreeColumn<T, ObservableCollection<T>>????
        var cast2 = column as TreeColumn<T, Collection<T>>;
        WriteLine("Cast to 'TreeColumn<T, Collection<T>>': ");
        WasCastSuccess(cast2);

        WriteLine("");
    }

    public void DoSomethingWithCollection(object collection) {

        var cast2 = collection as Collection<T>;
        WriteLine("Cast to 'Collection<T>': ");
        WasCastSuccess(cast2);

        WriteLine("");
    }

    private void WasCastSuccess(object o) {
        WriteLine(o != null ? "PERFECT!" : "Cast didn't work :(");
    }

    private void WriteLine(string msg) {
        _rowCounter++;
        Console.WriteLine(_rowCounter.ToString("00")+": "+msg);
    }
}

The console output is:

01: Cast to 'TreeColumn<T, Collection<T>>':
02: Cast didn't work :(
03:
04: Cast to 'TreeColumn<T, Collection<T>>':
05: PERFECT!
06:
07: Cast to 'Collection<T>':
08: PERFECT!
09:
10: Cast to 'Collection<T>':
11: PERFECT!
12:

I need to come up with something so line 2 of the output reads PERFECT!

Was it helpful?

Solution

Use out keyword to specify that the type parameter is covariant.

public interface ITreeColumn<T, out TValue> where TValue : Collection<T>
{
    // A lot declared in here..
}

public class TreeColumn<T, TValue> : ITreeColumn<T, TValue> where TValue : Collection<T>
{
    // A lot happens in here..
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top