在 C# 中,类型是否可以将其成员类型的接口公开为自己的接口
In c#, is it possible for a type to expose an interface of its member's type as its own
我不确定如何清楚地表达这个问题,所以这里有同一个问题的两个版本:
- struct/class 可以通过委托给它的 field/property 来实现接口吗?
- 我可以将 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(); }
}
}
这当然是一个非常人为和最小的例子。编写为它设计的接口时,好处会更大,尤其是当有很多方法 "map".
更新:
我知道我提供了一个糟糕的例子,但我只想尽可能使用最简单的例子。问题的核心不是关于特定场景。话虽如此,我的榜样不好;所以,为了更好地帮助喜欢看好例子的人提出问题,这里有一个稍微好一点的例子:
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
{
...
}
}
不,这不可能按照您描述的方式进行。您如何告诉编译器一个 "expose" 运算符优先于任何其他运算符?当您编写公开相同接口的两个内部对象时会发生什么?或者当两个 "exposed" 对象具有相同名称的共享属性或函数时?
你从这个符号中得到了什么?事实证明,您的要求是有可能的,但有 1 个限制。那就是你只能 "expose" 一种类型......我们称之为继承 :)
如果您从您想要 "expose" 的类型继承,您将获得相同的逻辑结果。您所描述的是复制接口的实现,但您想从 class 外部隐藏该事实?在我看来,这更像是一种反模式,它会阻碍更多而不是帮助。
将这些对象公开为 public 属性要简单得多,这样您就不必做出任何特殊考虑或检查类型接口之间的重复。以这种方式 "map" 属性的唯一原因是因为您想替换或修改基础类型的行为。否则你会省去麻烦并简单地公开它
你的 class 实现 IEnumerable 不是一个好的设计,许多有经验的开发人员在看到这个问题时会盯着他们的眼睛或简单地投反对票
我不得不查找它,但我记得在 SO 上有一个类似的请求:Why not inherit from List
该线程中有一些很好的健康讨论,还有许多其他关于 SO 的讨论围绕着这个主题。我们是你的朋友,但这是一堆蠕虫病毒,我们中的许多人都不希望在 C# 中打开它。我完全支持用其他语言对此进行探索,并且会喜欢阅读有关旅程的内容,但最终我们没有节省足够的击键次数,也没有提供允许更快编译或运行时策略的结构,以使其成为一个很好的功能请求
由于 Wiktor Zychla 在通过 link:
对问题的评论中提供的隐含答案,我发布了自己问题的答案
github.com/dotnet/roslyn/issues/13952
link 是针对一项功能的提案,这正是我在发布此问题时所想到的。所以我的问题的答案是 - 不,这是不可能的。
link 包含很好的讨论和 link 以提供更多信息。提议的语法是我唯一要重新考虑的。那里的一位评论者提供了 link 显示此功能的 Kotlin 语法,我认为这是迄今为止最好的并且比我想出的更好(虽然我没有提出语法,只是想说明我的问题)。
这是使用 Kotlin 语法的委托示例的更新版本:
public class School : IEnumerable<Student> by students
{
private List<Student> students;
...
}
我不确定如何清楚地表达这个问题,所以这里有同一个问题的两个版本:
- struct/class 可以通过委托给它的 field/property 来实现接口吗?
- 我可以将 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(); }
}
}
这当然是一个非常人为和最小的例子。编写为它设计的接口时,好处会更大,尤其是当有很多方法 "map".
更新: 我知道我提供了一个糟糕的例子,但我只想尽可能使用最简单的例子。问题的核心不是关于特定场景。话虽如此,我的榜样不好;所以,为了更好地帮助喜欢看好例子的人提出问题,这里有一个稍微好一点的例子:
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
{
...
}
}
不,这不可能按照您描述的方式进行。您如何告诉编译器一个 "expose" 运算符优先于任何其他运算符?当您编写公开相同接口的两个内部对象时会发生什么?或者当两个 "exposed" 对象具有相同名称的共享属性或函数时?
你从这个符号中得到了什么?事实证明,您的要求是有可能的,但有 1 个限制。那就是你只能 "expose" 一种类型......我们称之为继承 :) 如果您从您想要 "expose" 的类型继承,您将获得相同的逻辑结果。您所描述的是复制接口的实现,但您想从 class 外部隐藏该事实?在我看来,这更像是一种反模式,它会阻碍更多而不是帮助。
将这些对象公开为 public 属性要简单得多,这样您就不必做出任何特殊考虑或检查类型接口之间的重复。以这种方式 "map" 属性的唯一原因是因为您想替换或修改基础类型的行为。否则你会省去麻烦并简单地公开它
你的 class 实现 IEnumerable 不是一个好的设计,许多有经验的开发人员在看到这个问题时会盯着他们的眼睛或简单地投反对票
我不得不查找它,但我记得在 SO 上有一个类似的请求:Why not inherit from List
该线程中有一些很好的健康讨论,还有许多其他关于 SO 的讨论围绕着这个主题。我们是你的朋友,但这是一堆蠕虫病毒,我们中的许多人都不希望在 C# 中打开它。我完全支持用其他语言对此进行探索,并且会喜欢阅读有关旅程的内容,但最终我们没有节省足够的击键次数,也没有提供允许更快编译或运行时策略的结构,以使其成为一个很好的功能请求
由于 Wiktor Zychla 在通过 link:
对问题的评论中提供的隐含答案,我发布了自己问题的答案github.com/dotnet/roslyn/issues/13952
link 是针对一项功能的提案,这正是我在发布此问题时所想到的。所以我的问题的答案是 - 不,这是不可能的。
link 包含很好的讨论和 link 以提供更多信息。提议的语法是我唯一要重新考虑的。那里的一位评论者提供了 link 显示此功能的 Kotlin 语法,我认为这是迄今为止最好的并且比我想出的更好(虽然我没有提出语法,只是想说明我的问题)。
这是使用 Kotlin 语法的委托示例的更新版本:
public class School : IEnumerable<Student> by students
{
private List<Student> students;
...
}