在集合中存储两种类型对象的类型安全方法
我一直在实现增强的 Shunting-Yard 算法来解析算术表达式。该算法的一个方面是它维护一个Queue
和一个Stack
。
在我的实现中,Queue
包含Expressions
和Operators
。 堆栈
包含运算符
和括号
。
表达式
、括号
和运算符
没有任何共同点可以保证它们中的任何两个具有共享接口。
方法:
我当前的实现由实现
INotParanthesis
的Expression
和Operator
组成。Operator
和Paranthesis
实现INotExpression
。然后,我声明Queue
和Stack
。我不喜欢这个实现 - 这些接口似乎是为了更清晰的算法代码而进行的黑客攻击。我还认为接口应该描述对象是什么,而不是它不是什么。
另一方面,我也不想使用
到目前为止,我唯一想到的就是实现我自己的
NonParanthesisQueue
和NonExpressionStack
容器。这样做的优点是可以对从这些容器中拉出的对象进行更一致的类型检查 - 缺点是需要更多代码。
我的方法有任何合理的替代方案吗?
I've been implementing an enhanced Shunting-Yard algorithm for parsing an arithmetic expression. One aspect of the algorithm, is that it maintains a Queue
, and a Stack
.
In my implementation, the Queue
contains Expressions
and Operators
.
The Stack
contains Operators
and Parenthesis
.
Expressions
, Parenthesis
, and Operators
have nothing in common that warrants any two of them having a shared interface.
Approaches:
My current implementation consists of
Expression
andOperator
implementing aINotParanthesis
.Operator
andParanthesis
implement aINotExpression
. I then declareQueue <INotParanthesis>
, andStack <INotExpression>
.I don't like this implementation - these interfaces seem very much a hack for the purpose of cleaner algorithm code. I also believe that interfaces should describe what an object is, as opposed to what it isn't.
On the other hand, I also don't want to use collections of
<Object>
, as it can be difficult to be certain of the correctness of such code.The only one I've come up with, so far, is implementing my own
NonParanthesisQueue
andNonExpressionStack
containers. This has the advantage of more consistent type checking on objects getting pulled out of those containers - and the disadvantage of a lot more code.
Are there any reasonable alternatives to my approaches?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
听起来您真正想要的是 sum 类型。尽管 C# 没有内置这些,但函数式编程有一个技巧,您可以使用称为 Church 编码的技巧来实现此目的。它是完全类型安全的,不涉及强制转换,但是在 C# 中使用它有点奇怪,主要是由于类型推断的限制。
主要技巧是,我们不是使用属性和检查来检索两个替代方案之一,而是使用一个高阶函数
Map
,它接受两个函数作为参数,并根据存在的替代方案调用适当的函数。下面是如何使用它:这是
IEither
、Left
和Right
的实现。它们是完全通用的,可以在任何需要总和类型的地方使用。参考文献:
It sounds like what you really want is a sum type. Although C# does not have these built in, there's a trick from functional programming that you can use called Church encoding to achieve this. It's completely type safe with no casts involved, however it's a bit weird to use in C# mostly due to the limitations of the type inference.
The main trick is that instead of using properties and checks to retrieve one of the two alternatives, we have a higher order function
Map
that takes two functions as arguments and calls the appropriate one depending on which alternative was present. Here's how you would use it:Here's the implementation of
IEither
,Left
andRight
. They are fully generic and could be used anywhere you want a sum type.References:
也许您可以为每个类型定义一个小持有者类型,一个具有 Expression 属性和 Operator 属性,另一个具有 Operator 属性和 Parenthesis 属性。访问器和构造器可以断言或以其他方式确保只填充一个。队列和堆栈将各自包含适当的持有者类型。
有点尴尬,但类型安全且可行。
希望有人能有更聪明的主意。
Maybe you could define a small holder type for each, one with an Expression property and an Operator property and the other with an Operator property and a Parenthesis property. Accessors and constructors could assert or otherwise ensure that only one is populated. The queue and the stack would each contain the appropriate holder type.
A little awkward but typesafe and workable.
Hopefully someone will have a more clever idea.