接口作为属性

时间:2011-01-19 22:26:19

标签: c# .net

我有一个接口和两个实现它的类。我收到编译错误,我不太清楚为什么。

interface IPerson
{
    ICollection<string> NickNames{get;set;}
}
class ObservablePerson : IPerson
{
    ObservableCollection<string> NickNames{get;set;}
}
class ListPerson : IPerson
{
    List<string> NickNames{get;set;}
}

我在理解为什么这不起作用时遇到了一些麻烦,因为List和ObservableCollection都实现了ICollection。

5 个答案:

答案 0 :(得分:6)

  

我在理解为什么这不起作用时遇到了一些麻烦,因为List和ObservableCollection都实现了ICollection。

是的,但界面指出返回ICollection<string>。基础类型可以是ObservableCollection<string>List<string>,但签名需要符合接口。 ObservableCollection<string>ICollection<string>,但ICollection<string>不一定是ObservableCollection<string>

此外,您的方法需要公开(它们目前是私有的)。接口不处理私有或受保护的方法,它定义了 public 接口。

答案 1 :(得分:1)

应该是

interface IPerson
{
    ICollection<string> NickNames{get;set;}
}
class ObservablePerson : IPerson
{
    ICollection<string> NickNames{get;set;}
}
class ListPerson : IPerson
{
    ICollection<string> NickNames{get;set;}
}

在实现中,您可以返回List对象或ObservableCollection

已编辑的代码

interface IPerson
    {
        ICollection<string> NickNames{get;set;}
    }

public class ObservablePerson : IPerson
    {
        ICollection<string> nickNames = new ObservableCollection<string>();

        public ICollection<string> IPerson.NickNames
        {
            get
            {
                return nickNames;
            }
            set
            {
                nickNames = value;
            }
        }
    }
    public class ListPerson : IPerson
    {
        ICollection<string> nickNames = new List<string>();

        public ICollection<string> IPerson.NickNames
        {
            get
            {
                return nickNames;
            }
            set
            {
                nickNames = value;
            }
        }
    }

答案 2 :(得分:0)

您的问题是编译器希望您的两个子类都返回一种ICollection类型。您可以通过get访问器返回List或ObservableCollection,但声明的成员类型需要保留ICollection。

答案 3 :(得分:0)

编译器将坚持精确类型匹配,但您可以在类(而不是通过接口)访问时隐藏属性。但请注意,在通过界面进行设置时,某人可能会分配不同类型的ICollection<string> - 因此这会导致异常。

interface IPerson
{
    ICollection<string> NickNames { get; set; }
}
class ObservablePerson : IPerson
{
    public new ObservableCollection<string> NickNames { get; set; }
    ICollection<string> IPerson.NickNames
    {
        get { return NickNames; }
        set { NickNames = (ObservableCollection<string>)value; }
    }
}
class ListPerson : IPerson
{
    public new List<string> NickNames { get; set; }
    ICollection<string> IPerson.NickNames
    {
        get { return NickNames; }
        set { NickNames = (List<string>)value; }
    }
}

答案 4 :(得分:0)

我遇到了类似的问题,我的一个伙伴提出了一个很好的解决方案:通用类型。这是你可以做的:

public interface IPerson<CollectionType> where CollectionType : ICollection<string>
{
    CollectionType NickNames { get; set; }
}

class ObservablePerson : IPerson<ObservableCollection<string>>
{
    public ObservableCollection<string> NickNames { get; set; }
}

public class ListPerson : IPerson<List<string>>
{
    public List<string> NickNames { get; set; }
}

这里,“CollectionType”是一个Generic,并且可以根据需要命名(在整个.NET Framework中它通常称为T,但是给它一个有意义的名称我觉得很有帮助)。这将允许您在那些ObservablePerson和ListPerson上实现一个接口,同时在每个上都有不同类型的NickNames属性(尽管您用于CollectionType的任何类型都需要实现ICollection)。