在c#中,类型是否可以将其成员类型的接口公开为其自己的接口

时间:2017-03-16 09:29:05

标签: c# interface composition delegation

我不确定如何清楚地说出这个问题,所以这里还有两个版本的同一个问题:

  • struct / class可以通过委托给它的field / property来实现接口吗?
  • 我可以将字段/属性类型实现的接口映射到其struct / class吗?

这是一个添加了伪语法的代码示例,希望能够表明我的意思:

public class School : IEnumerable<Student>
{
    private List<Student> students expose IEnumerable<Student>;
    ...
}

如果目前无法做到这一点,是否有可能? ......或者这种方法存在一些严重问题吗?我认为这可能只是语法糖来摆脱锅炉板代码,否则它将在功能上相同。例如:

public class School : IEnumerable<Student>
{
    private List<Student> students;
    ...
    public IEnumerator<Student> GetEnumerator() { return students.GetEnumerator(); }
    IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}

}

这当然是一个非常人为的例子。在编写为其设计的界面时,好处会更大,特别是当有很多方法可以“映射”时。

更新 我知道我提供了一个可怕的例子,但我只是想用最简单的例子。问题的核心不是特定情况。话虽如此,我的榜样很糟糕;所以,为了更好地帮助那些喜欢看到一个好例子的人,这里有一个更好的例子:

public interface IValidPeriod
{
    DateTime ValidFrom { get; }
    DateTime ValidTo { get; }
    DateTime ValidThrough { get; }
    int DaysValid { get; }
}

public class ValidPeriod : IValidPeriod
{
    public DateTime ValidFrom { get; private set; }
    public DateTime ValidTo { get; private set; }
    public DateTime ValidThrough { get { return ValidTo.AddDays(1); } }
    public int DaysValid { get { return (ValidTo - ValidFrom).Days; } }

    public ValidPeriod(DateTime from, DateTime to)
    {
        ValidFrom = from;
        ValidTo = to;
    }
}

public class Agreement : IValidPeriod
{
    ...
    public ValidPeriod ValidPeriod { get; private set; } exposes IValidPeriod;
    ...
}

public class Contract : IValidPeriod, ICancellable
{
    private Agreement agreement exposes IValidPeriod;
    ...
}

public class Payment : IValidPeriod, ICancellable
{
    public DateTime StartDate { get; set; }

    private ValidPeriod validPeriod
    {
        get { return new ValidPeriod(StartDate, DateTime.Max); }
    } exposes IValidPeriod;
    ...
}

public static class SomeUtility
{
    public static void CancelIfValidBefore<T>(List<T> items, DateTime date)
        where T : IValidPeriod, ICancellable
    {
        ...
    }
}

2 个答案:

答案 0 :(得分:2)

由于Wiktor Zychla在通过链接对该问题发表的评论中提供了一个隐含的答案,我正在回答我自己的问题:

github.com/dotnet/roslyn/issues/13952

链接是针对某个功能的提案,这正是我在发布此问题时的想法。所以我的问题的答案是 - 不,这是不可能的。

该链接包含良好的讨论和更多信息的链接。建议的语法是我唯一要重新考虑的事情。其中一位评论者提供了link显示此功能的Kotlin语法,我认为这是迄今为止最好的,并且比我想出的更好(虽然我没有提出语法,只是试图说明我的问题)。

以下是使用Kotlin语法的代理示例的更新版本:

public class School : IEnumerable<Student> by students
{
    private List<Student> students;
    ...
}

答案 1 :(得分:0)

  1. 这不可能按照你所描述的方式进行。你怎么告诉编译器一个&#34;暴露&#34;运算符优先于其他运算符?编写暴露相同接口的两个内部对象时会发生什么?或当两个&#34;暴露&#34;对象具有共享属性或同名函数?

  2. 你从这个符号中获得了什么?事实证明,你所要求的是一种可能,有1个限制。那就是你只能&#34;暴露&#34;一种类型......我们称之为继承:) 如果您继承了您想要的类型,那么您将获得相同的逻辑结果&#34;公开&#34;。您所描述的是复制接口的实现,但是您想要从类外部隐藏该事实?对我来说,这更像是一种反模式,它会阻碍更多它的帮助。

  3. 将这些对象公开为公共属性要简单得多,那么您不必进行任何特殊考虑或检查类型接口之间的重复。 &#34; map&#34;的唯一原因这种方式的属性是因为您想要替换或修改基础类型的行为。否则你会省去麻烦并简单地暴露它

  4. 你的实现IEnumerable的课程并不是一个好的设计,会有很多经验丰富的开发人员在他们看到这个问题时抓住他们的电子邮件或者简单地投票

  5. 我不得不查一查,但我记得SO上的类似请求:Why not inherit from List

    在该主题中,该主题和其他许多内容都有一些良好的健康讨论。我们在这里是你的朋友,但这是一种蠕虫病毒,我们很多人都不愿意在C#中打开。我完全支持在其他语言中探索这个并且会喜欢阅读有关旅程但最终我们没有保存足够的键击,也没有提供一个允许更快的编译或运行时策略的结构来使这个功能成为一个很好的功能