Robert Hegner
Robert Hegner

Reputation: 9376

Is interface inheritance the right thing to do here, and why does it not work?

I'm implementing some type (MyType in the example below) which has a Collection property. Inside MyType I don't really care what kind of collection this is. The only thing I care is that it implements IEnumerable<String> and INotifyCollectionChanged. How would I implement the Collection property with these restrictions?

Here is what I've tried:

I created a new interface:

interface INotifyEnumerableCollectionChanged<T> : IEnumerable<T>, INotifyCollectionChanged {}

and made the Collection property in MyType of type INotifyEnumerableCollectionChanged<String>. This seems to work inside MyType. It looks like i can enumerate over that collection and register the CollectionChanged event.

But I can't set this property to a collection (MyCollection in the example below), even tough MyCollection implements both IEnumerable<String> and INotifyCollectionChanged.

The compiler says:

Cannot implicitly convert type 'InterfaceInheranceTest.Program.MyCollection' to 'InterfaceInheranceTest.Program.INotifyEnumerableCollectionChanged'. An explicit conversion exists (are you missing a cast?)

What is the right way to do this?

Here is the full example code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;

namespace InterfaceInheranceTest
{
    class Program
    {

        interface INotifyEnumerableCollectionChanged<T> : IEnumerable<T>, INotifyCollectionChanged {}

        class MyCollection : IEnumerable<String>, INotifyCollectionChanged
        {

            IEnumerator<String> IEnumerable<String>.GetEnumerator()
            { throw new NotImplementedException(); }

            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            { throw new NotImplementedException(); }

            public event NotifyCollectionChangedEventHandler CollectionChanged;
        }

        class MyType
        {
            private INotifyEnumerableCollectionChanged<String> _Collection;

            public INotifyEnumerableCollectionChanged<String> Collection
            {
                get { return _Collection;  }
                set
                {
                    _Collection = value;
                    _Collection.CollectionChanged += new NotifyCollectionChangedEventHandler(_Collection_CollectionChanged);
                    foreach (var item in _Collection)
                    {
                        Console.WriteLine(item);
                    }
                }
            }

            void _Collection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            { throw new NotImplementedException(); }
        }


        static void Main(string[] args)
        {
            var collection = new MyCollection();
            var type = new MyType();
            type.Collection = collection;   // compiler doesn't like this!
        }
    }
}

Upvotes: 1

Views: 132

Answers (2)

Nop
Nop

Reputation: 151

You created a new interface but you don't use it.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;

namespace InterfaceInheranceTest
{
    class Program
    {

        interface INotifyEnumerableCollectionChanged<T> : IEnumerable<T>, INotifyCollectionChanged {}

        class MyCollection : INotifyEnumerableCollectionChanged<String> // Use your interface
        {

            IEnumerator<String> IEnumerable<String>.GetEnumerator()
            { throw new NotImplementedException(); }

            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            { throw new NotImplementedException(); }

            public event NotifyCollectionChangedEventHandler CollectionChanged;
        }

        class MyType
        {
            private INotifyEnumerableCollectionChanged<String> _Collection;

            public INotifyEnumerableCollectionChanged<String> Collection
            {
                get { return _Collection;  }
                set
                {
                    _Collection = value;
                    _Collection.CollectionChanged += new NotifyCollectionChangedEventHandler(_Collection_CollectionChanged);
                    foreach (var item in _Collection)
                    {
                        Console.WriteLine(item);
                    }
                }
            }

            void _Collection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            { throw new NotImplementedException(); }
        }


        static void Main(string[] args)
        {
            var collection = new MyCollection();
            var type = new MyType();
            type.Collection = collection;   // compiler doesn't like this!
        }
    }
}

Defining same methods do not mean it's the same type.

Upvotes: 1

Oded
Oded

Reputation: 498992

Your class needs to implement INotifyEnumerableCollectionChanged<T>.

    class MyCollection : INotifyEnumerableCollectionChanged<string>. 
                         IEnumerable<string>, INotifyCollectionChanged
    {

        IEnumerator<String> IEnumerable<String>.GetEnumerator()
        { throw new NotImplementedException(); }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        { throw new NotImplementedException(); }

        public event NotifyCollectionChangedEventHandler CollectionChanged;
    }

This is needed because the variable you use(_collection) is of type INotifyEnumerableCollectionChanged<T>. However, your class - MyCollectionChanged does not implement this interface, so can't be assigned as a reference to the variable.

Upvotes: 3

Related Questions