抽象阻碍了自定义类型的使用,实现中要遵循的规则是什么?

时间:2010-11-01 19:19:19

标签: c# implementation base-class type-systems

我已经构建了一个自定义类型系统,用于在应用程序内部使用C#脚本。这些脚本是即时编译的,允许与应用程序内部数据进行交互。此类型系统使用IValue之类的接口以抽象方式设计。 IValue的实施可以是RefStringRefIntegerRefDouble(在许多其他方面,但这足以证明我的问题)。

现在我们陷入了困境......使用这些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,...)
  • 声明隐式转换运算符
  • 声明显式转换为基类型(以避免隐式转换为int !!经常会发生什么,但为什么?)
  • 为避免模糊调用,不应在基类和派生类中重写+, - ,/,*运算符。 [那是什么方式去?我在派生类中执行了重载操作,这需要在使用时进行转换,这又是丑陋的......]

1 个答案:

答案 0 :(得分:1)

如果您应该能够对所有Add进行IValue操作,那么界面是否应该包含Add方法?然后你可以做return a.Add(b);,并将如何执行操作的知识推送到每种类型。

现在看来,有一个问题是,a RefString bRefIntegerT Add<T>(T a, T b) where T : IValue { return a.Add(b); } 时,您可能会拨打电话,这可能不是您想要的。泛型可以帮助解决这个问题:

{{1}}

(当然你需要添加空检查和适当的)