首先,很抱歉这篇冗长的帖子。基本上,我的问题是:
我正在尝试在 C# 中重现以下 F# 可区分联合类型:
type Relation =
| LessThan of obj * obj
| EqualTo of obj * obj
| GreaterThan of obj * obj
谁能提出比以下更简单的基于接口的解决方案?
interface IRelation // concrete types represent ◊ in the expression "Subject ◊ Object"
{
object Subject { get; }
object Object { get; }
}
struct LessThanRelation : IRelation { … }
struct EqualToRelation : IRelation { … }
struct GreaterThanRelation : IRelation { … }
我所有的算法都识别这三种关系类型,而且只有这些,所以我需要防止IRelation
第三方(即其他程序集)进一步实现。
脚注:对某些人来说,如果我的接口和算法在面向对象/多态性方面是正确的,那么将第三方实现注入到我的算法方法中并不重要,只要接口是正确实施。这是一个有效的批评。但是,让我们暂时假设在这种情况下我更喜欢函数式编程风格而不是严格的面向对象。
到目前为止,我最好的想法是将所有上述类型声明为internal
(即外人永远不会直接看到它们)并创建一个代理类型Relation
,这将是第三方唯一可见的类型:
public struct Relation // constructors etc. are omitted here for brevity's sake
{
public RelationType Type { get { … /* concrete type of value -> enum value */ } }
public Relation Subject { get { return value.Subject; } }
public Relation Object { get { return value.Object; } }
internal readonly IRelation value;
}
public enum RelationType
{
LessThan,
EqualTo,
GreaterThan
}
到目前为止一切都很好,但它变得更加复杂......
...如果我为具体关系类型公开工厂方法:
public Relation CreateLessThanRelation(…) { return new Relation { value = new LessThanRelation { … } }; }
…每当我公开一个处理关系类型的算法时,因为我必须从/映射到代理类型:
public … ExposedAlgorithm(this IEnumerable<Relation> relations) { // forward unwrapped IRelation objects to an internal algorithm method: return InternalAlgorithm(from relation in relations select relation.value); }