Во-первых, извините за длинный пост.По сути, мой вопрос таков:
Я пытаюсь воспроизвести в 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);
}