在C#中设计接口的问题:示例项目

时间:2018-08-21 15:39:56

标签: c# class oop design-patterns interface

我在设计界面时遇到问题

我有这些接口:

interface IField {

}

interface IScreenField : IField {

}

interface ITable { 
    CustomCollection<IField> CustomCollection { get; set; }
}

interface IScreen
{
    AnotherCustomCollection<IScreenField> AnotherCustomCollection { get; set; }
}

IScreen接口应继承自ITable,但显示错误,我必须实现IField的集合,但我已经实现了IScreenField

解决方案是什么?

我上传了一个示例项目以进一步说明问题

您可以在Screen类中查看错误消息:

Screen未实现接口成员ITable.FieldsScreen.Fields无法实现ITable.Fields,因为它没有匹配的返回类型CusomCollection<IField>

以下是示例: Sample project

3 个答案:

答案 0 :(得分:0)

此示例的描述可帮助您解决问题:如果IExample2继承了另一个Interface,则在实现IExample2时需要实现  接口+ IExample2中继承的接口的方法中声明的所有方法(属性等...)。请记住,实现接口时,必须实现该接口的所有成员(甚至必须实现链中所有接口的成员),并且所有返回类型在接口和类中必须相同。 / p>

interface IExample
{
    void Method1();
}

interface IExample2 : IExample
{
    void Method2();
}

class Screen : IExample2
{
    public void Method2()
    {

    }

    public void Method1()
    {

    }
}

链示例

interface IExample
{
    void Method1();
}

interface IExample2 : IExample
{
    void Method2();
}

interface IExample3 : IExample2
{
    void Method3();
}

答案 1 :(得分:0)

您可以执行以下操作:

public class Screen : IScreen
{
    public string Name { get; set; }

    public string Title { get; set; }
    public string Description { get; set; }

    public AnotherCustomCollection<IBaseField> Fields { get; set; }

    CustomCollection<IField> ITable.Fields
    {
        get
        {
            throw new System.NotSupportedException();
        }
    }
}

显然,编译器喜欢这种方式,如果您执行以下操作:

public static void Main(string[] args)
    {
        var collection = new List<IScreen>()
        {
            new Screen
            {
                Fields = new AnotherCustomCollection<ScreenInterface.IBaseField>
                {
                    new TextField()
                    {
                        Name = "Hello"
                    }
                }
            }
        };

        var y = collection.First();

        //Prints "Hello"
        Console.WriteLine(string.Join(" ", y.Fields.Select(x => x.Name)));
        Console.ReadLine();
    }

但是,如果您正在使用上层界面(ITable)

public static void Main(string[] args)
    {
        var collection = new List<ITable>() //here
        {
            new Screen
            {
                Fields = new AnotherCustomCollection<ScreenInterface.IBaseField>
                {
                    new TextField()
                    {
                        Name = "Hello"
                    }
                }
            }
        };

        var y = collection.First();

        //Throws NotSupportedException
        Console.WriteLine(string.Join(" ", y.Fields.Select(x => x.Name)));
        Console.ReadLine();
    }

我的猜测是没有泛型继承的概念,如果将AnotherCustomCollection的条件泛型参数从IBaseField切换为IField可以证明这一点。如果引发异常,请返回Fields上的公共Screen.ITable.Fields属性。编译器将自动识别具体属性,并且一切正常。

因此,要使其正常工作,请定义隐式运算符或自定义getter:

public class Screen : IScreen
{
    public string Name { get; set; }

    public string Title { get; set; }
    public string Description { get; set; }

    public AnotherCustomCollection<IBaseField> Fields { get; set; }

    CustomCollection<IField> ITable.Fields
    {
        get
        {
            var customCollection = new CustomCollection<IField>();
            customCollection.AddRange(Fields);
            return customCollection;
        }
    }
}

答案 2 :(得分:0)

  

这是我在之前的帖子中发布的答案。由于您之前的问题在我无法解决之前已被搁置   提交答案。

不查看完整代码很难识别问题,但是基于您所说的,我相信您已经明确实现了IScreenField,并且编译器无法找到{{1 }}。

结帐以下以获取更多信息: https://www.codeproject.com/Articles/1000374/Explicit-Interface-VS-Implicit-Interface-in-Csharp

更新:查看代码后

首先,您需要了解接口的隐式和显式实现之间的区别:

  

隐式::您可以访问界面属性和属性,就好像它们是类的一部分一样。   显式::您只能在将类视为已实现的接口时访问属性和属性。

IField类的问题在于它实现了Screen接口,而该接口又实现了IScreen接口。这两个接口都有一个名为ITable的属性。

因此,问题浮出水面,您需要 明确地实现Fields类中的Fields属性。

注意:与您使用不同的返回类型无关。由于您在两个接口中都实现了Screen属性,因此假设从每个接口访问该属性时,您期望的值是不同的。

Fields

现在如何访问它们?要访问每个接口的public class Screen : IScreen { public string Name { get; set; } AnotherCustomCollection<IBaseField> IScreen.Fields { get { return default(AnotherCustomCollection<IBaseField>); } } CustomCollection<IField> ITable.Fields { get { return default(CustomCollection<IField>); } } public string Title { get; set; } public string Description { get; set; } } 属性,您需要访问Fields对象 as

  

例如:
  Screen

     

var screen = new Screen();

     

var fields = screen.Fields; // Error

     

var fields = (screen as IScreen).Fields; // returns property value of IScreen Fields

以下是完整的代码: https://dotnetfiddle.net/5KS0Xd

希望这很有帮助。祝一切顺利,愉快。