2017-03-16 37 views
1

我不知道怎么甚至明确短语这个问题,所以这里有两个版本的同一问题:在C#中,有可能是一种揭露其成员的接口类型作为自己

  • 结构/类可以通过委托给它的字段/属性来实现一个接口吗?
  • 我可以将由字段/属性类型实现的接口映射到其结构/类吗?

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

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 
    { 
     ... 
    } 
} 
+4

见https://github.com/dotnet/roslyn/issues/13952 –

+0

的第一个问题是,为什么你认为'学校**是**学生的枚举?它有学生,也有教师和其他个人。 '学校'不应该实现那个接口,有公共方法返回学生是绰绰有余的。除非你有更好的例子,否则我怀疑这个功能请求确实是需要的,这基本上是一个尝试解决方案的问题。自动实现*少*方法?我可以自己做,我确实希望明确地看到这个实现,而不是通过一些神秘的'expose'操作符。 – Sinatr

+0

没有“委派”,接口没有执行任何操作。它只是要求你提供一个实现。从列表中派生你的类将是一种简单的方法,但是通常你不能重写Add()方法。委托一份私人名单是很好的,而且很简单。 –

回答

2

我张贴的答案,我自己的问题由于通过链接在评论由Wiktor的Zychla提供给这个问题的答案隐含:

github.com/dotnet/roslyn/issues/13952

的链接是一个提议的功能,正是我发布这个问题时想到的。所以我的问题的答案是 - 不,这是不可能的。

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

这里使用科特林的语法我国代表团例子的更新版本:

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

该类的“公共接口”不应该如何实现,因此我不喜欢Kotlin的语法。 PS,一个更好的例子是一个包含人物的学生,因为老师也可以包含一个人物。如果一个人既是老师又是学生,老师对象和学生对象都包含同一个人对象。 (例如,将它用于GetName()。) –

0
  1. 不,这是不可能的,你所描述的方式。你如何告诉编译器一个“暴露”运算符优先于其他运算符?当你编写两个公开相同接口的内部对象时会发生什么?或者当两个“暴露”对象具有共享属性或同名的函数?

  2. 你从这个符号中得到了什么?事实证明,你所要求的是有可能的,有一个限制。那就是你只能“暴露”一种类型......我们称之为继承:) 如果你从你想要“暴露”的类型继承,你会得到同样的逻辑结果。你所描述的是复制一个接口的实现,但你想从课堂外隐藏这个事实?这听起来对我来说更多的是一种反对模式,它会阻碍更多的事情。

  3. 将这些对象作为公共属性公开显示是非常简单的,那么您不必在整个类型接口中进行任何特殊考虑或检查重复。以这种方式“映射”属性的唯一原因是因为您想要替换或修改基础类型的行为。否则,你将节省的麻烦,简单地将其暴露

  4. 你的类实现IEnumerable的是不是一个良好的设计和将会有很多有经验的开发人员在他们的余仁生或干脆反对投票扣,当他们看到这个问题

我不得不查看它,但我记得在SO上有类似的请求:Why not inherit from List

在这个主题上,该主题和其他许多关于SO的讨论中都有一些很好的健康讨论。我们在这里是你的朋友,但这是一堆蠕虫,我们许多人不希望用C#打开。我完全支持在其他语言中对此进行探索,并会喜欢阅读旅程,但最终我们没有节省足够的按键笔划,也不会提供允许更快编译或运行时策略以使其成为良好功能请求的结构

+1

1.我不明白为什么这是不可能的。如果你认为它是一个语法糖,那么编译器可以简单地将它扩展到一个方法列表中,并分别调用该字段。然后所有的冲突将以通常的方式解决。 2.为什么从外面隐藏?如果这个类实现了接口,那么它暴露了已实现的成员 3.我不明白为什么用手写这些成员更简单 4.这是一个人为的例子。 我不是主张这个功能,但我不明白所有的批评。 – username

+0

好的,所以有可能使它成为一个功能,并让编译器意识到所有这些......但是我们得到了什么?上面的第3点是国际海事组织一个非常难以忽视的理由,如果你只是简单地转发暴露类型的所有属性和方法,那为什么它不只是一个属性?但是,如何处理覆盖,我们是否允许类有选择地覆盖某些属性,而其他所有属性只是通过暴露类型传播?我觉得这种功能会破坏我们c#语言的稳定性和简单性。 –

+0

如果您想要实现的只是保存一些关键笔划,那么您应该考虑通过属性注入技术来重新编写IL。这当然是可行的。我认为这个特征的不确定性会使一些代码难以解释。 –

相关问题