在C#.NET中实现接口

时间:2012-11-06 09:04:09

标签: c# .net interface compilation

考虑以下界面

public interface ICustomData
{
    String CustomData { set; get; }
}

根据MSDN文档,接口成员会自动公开。

让我说我现在想要实现我的界面:

public class CustomDataHandler : ICustomData
{
}

这会在编译时中断,告诉我我没有实现“CustomData”

另一方面,这将起作用:

public class CustomDataHandler : ICustomData
{
    public String CustomData { set; get; }
}

我的问题是:如果接口的成员自动公开,为什么我必须在类中声明实现?如果接口声明在语法上与类声明完全相同,为什么编译器不能从我的接口自动推断出这个?

修改

我的理由。想象一下你正在构建数据模型,实体等的场景。我可能会像这样编写一些这些模型的接口:

public interface IUserAccount
{
    Guid Identity { set; get; }
    String FirstName { set; get; }
    String LastName { set; get; }
    String EmailAddress { set; get; }
    String Password { set; get; }
}

public interface IUserDataEntry
{
    Guid DataIdentity { set; get; }
    String DataName { set; get; }
    String Data { set; get; }
}

如此构建模型会简单得多:

public class UserAccount : IUserAccount
{
}

public class UserDataEntry : IUserDataEntry
{
}

public class Combined : IUserAccount, IUserDataEntry
{
}

6 个答案:

答案 0 :(得分:3)

接口不在那里提供实现,它是定义合同的。然后,这允许构建实现它的不同实现。

答案 1 :(得分:2)

它们在语法上可能完全相同,但它们意味着不同的东西(即它们在语义上相同)。

在接口中,语法意味着实现类必须公开这样的属性,并在其认为合适时(显式或隐式)实现getset访问器。界面只定义了类必须提供的外向行为;它没有提供该行为的任何实现。

在类中,语法是“auto-property”,接口定义的属性的实现getset访问器是隐式的转换为具有支持字段的完整实现。它在编译时看起来像这样:

public class CustomDataHandler : ICustomData
{
    private string customData;

    public string CustomData
    {
        get
        {
            return customData;
        }
        set
        {
            customData = value;
        }
    }
}

答案 2 :(得分:1)

您正在隐式实现该接口。在这种情况下,类的方法签名必须与接口的签名(包括可访问性)匹配。确保方法被标记为公共可确保在查看类时没有意外,例如:

public class CustomDataHandler : ICustomData
{
  String CustomData {get; set}
  String PrivateCustomData {get;set;}
}

即使两个属性都声明相同,CustomData属性也会因为它在接口上声明而公开,即使声明看起来与PrivateCustomData相同。这将是不一致的,并导致更难维护代码。

如果您不想设置访问修饰符,可以显式实现界面:

public class CustomDataHandler : ICustomData
{
    String ICustomData.CustomData { set; get; }
}

答案 3 :(得分:0)

接口声明仅指定接口定义的行为。在您的情况下,这是一个名为CustomData的属性,它具有getset(它是读/写属性),类型为string

实现接口的类需要完全按照指定实现

现在,在您的情况下,您使用的是自动实现的属性{ get; set; },它看起来与接口声明相同,但您也可以在get或set方法中使用支持字段和行为。

答案 4 :(得分:0)

您必须明确地实现它,因为......您不仅限于以这种方式实现它。您可以使用字段,或在方法中执行其他操作。接口只是保证此方法存在的方法契约。

public class CustomDataHandler : ICustomData
{
    public String CustomData
    {
        get { return "None of your business!"; }
        set { } // Decide to do nothing
    }
}

界面只保证这种方法会存在。不是你要用它做什么。

编辑:至于您对问题的编辑,如果您只想为类集合实现一次该方法,则可能会尝试使用父类而不是接口。但是,虽然您可以组合界面,但您无法组合父类。但是,您可以在类层次结构的不同位置添加接口。

答案 5 :(得分:0)

以下是派生类中CustomData属性为private的示例:

public class CustomDataHandler : ICustomData
{
    private string CustomData { set; get; }

    string ICustomData.CustomData { get; set; }
}

但是这段代码编译,因为还有一个显式的属性实现。

因此,public修饰符在这种情况下不是多余的。