我已经在应用程序中的C#脚本中构建了一个自定义类型系统。这些脚本是直接编译的,并允许与应用程序内部数据进行交互。此型型系统的设计是使用诸如 IValue. 。实施 IValue 可以是一个 RefString, RefInteger, RefDouble (除其他许多地方,但这足以证明我的问题)。

现在我们到了我被卡住的地步...使用这些 IValue 对象有些不自然。它被认为是始终使用接口与对象交互的好设计,但是没有可能定义隐式转换或对接口的运算符过载。这使得不可避免的丑陋明确铸造的情况使正确的操作员可以使用。

例子:

IValue Add(IValue a, IValue b)
{
    //return a+b; // won't work: which operator +() to use?
    return (RefInteger)a + (RefInteger)b;
}

对于涉及价值类型的表达式中的c#,提供了隐式转换。设计这样的自定义系统的好方法是什么?

我重写了典型系统的删除 IValue 接口并引入 RefValue 基类。这样,已经可以消除显式演员的一部分。我在此基类中实现了一些操作员的过载,但这造成了默认转换操作员的很多麻烦……除此之外,在操作员实施中实现的逻辑牵涉到有关系统中类型的大量知识。我认为这仍然是人们必须走的方式,但是要以良好和安全的方式实施它的规则是什么?

编辑: :挣扎过一会儿后,我发现的一些规则是:

  • 仅从基本类型(int,double,string,...)声明隐式转换算子
  • 将明确转换为基础类型(避免隐含的铸件!
  • 为了避免模棱两可的调用 +, - , /, *在基类和派生类中不应覆盖运算符。 [那怎么办?我在派生的类中进行了操作过载,这需要在使用时施放,这再次丑陋...
有帮助吗?

解决方案

如果您应该能够 Add 所有人的操作 IValueS,也许接口应包括一个 Add 方法?那你可以做 return a.Add(b);, ,并推动如何将操作执行到每种类型的知识。

一个问题是,正如现在看起来,您可以在哪里接听电话 aRefStringbRefInteger, ,这可能不是您想要的。仿制药可以帮助解决:

T Add<T>(T a, T b) where T : IValue
{
    return a.Add(b);
}

(当然,您需要添加无效检查,以便适当)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top