简体   繁体   中英

Generic Interface hiding of parent non-generic interface methods

I want to implement a generic class AppContextItem with the generic Interface IAppcontextItem. As I want to store multiple AppContextItems inside of a List without knowing the exact type (and also I want to be able to mix multiple typed AppContextItems inside the list). I created another non-generic Interface IAppContextItem. The generic implementation of IAppContextItem should hide the non-generic fields but it somehow doesn't, because I get an compile error that tells me I need to implement Element with return type object. Is it impossible to do what I want or did I get something wrong?

IAppcontextItem.cs

public interface IAppContextItem
{

    string Key { get; set; }

    object Element { get; set; }

}

public interface IAppContextItem<T> : IAppContextItem 
    where T : class
{
    new string Key { get; set; }
    new T Element { get; set; }
}

AppContextItem.cs

public class AppContextItem<T> : IAppContextItem<T> where T : class
{

    private string key = string.Empty;
    private T element;

    public string Key
    {
        get { return key; }
        set { key = value; }
    }

    public T Element
    {
        get { return element; }
        set { element = value; }
    }

You have to implement both the T Elemen t and object Element properties. The implementation for object Element will look like:

object IAppContextItem.Element
{
   get; set;
}

You can then cast it to the correct interface:

 AppContextItem<MainApp> app = new AppContextItem<MainApp>();
 IAppContextItem iapp = (IAppContextItem)app;
 object o = iapp.Element;

This is called Explicit Interface Implementation .

If you want to have a different implementation of IAppContextItem.Key and IAppContextItem<T>.Key you can use explicit interface implementation like this:

string IAppContextItem.Key
{
    get { return key + "A"; }
    set { key = value; }
}

string IAppContextItem<T>.Key
{
    get { return key + "B"; }
    set { key = value; }
}

This is the sentence that indicates your misunderstanding:

The generic implementation of IAppContextItem should hide the non-generic fields but it somehow doesn't, because I get an compile error that tells me I need to implement Element with return type object.

An interface is a contract; it says "an implementation of this interface is required to provide the following methods and properties...". Hiding a method or property via inheritance neither fulfills that part of the contract nor eliminates the requirements that the contract imposes upon the implementer.

The contract says that an implementation is required to provide four properties. That some of those properties have the same names as others does not in any way eliminate the requirement that you provide every property described by the contract. That two of those properties are "more visible" than the other two does not change the fact that the contract requires four properties. You've still got to implement all four; their visibility doesn't factor into it at all.

Wouter de Kort's answer glosses over an important point: If you want both Element properties to refer to the same object, you must not do this:

object IAppContextItem.Element
{
    get; set;
}

If you do, you'll find that you have created an auto property for the interface's Element property, whose value is independent from the T -typed Element property. Instead, you should do this:

object IAppContextItem.Element
{
    get { return this.Element; }
    set
    {
        if (!(value is T))
            throw // ... some exception
        this.Element = (T)value;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM