黑板是在运行时存储和获取通用键值对的对象。它可以通过Dictionary<object,object>实现。一些子系统写在黑板上,以让其他子系统从黑板上读取。

存放黑板的系统不知道里面有什么类型的物体,什么时候。特定键的作者和读者始终了解并同意键值对的类型。为了便于实现而牺牲了编译时检查-有大量的编写者和读者,并且不断地对其进行迭代。

我的黑板界面如下所示:

interface Blackboard {
    bool HasKey(object key);
    T GetValue<T>(object key);
}

作家创建并返回黑板,因此SetValue(key, value)可以作为实现细节。

我最初的实现使用Dictionary<object,object>,一切都很好。但是,此黑板必须快速且无分配。这是不可商议的。如果作者将浮点值推到黑板上,那么天真的实现会将int放入字典中。

我不能在实现类BlackboardImpl<ValueType> : Blackboard上使用泛型类型,因为值类型在黑板上不是恒定的。

我可以将多个内部字典,Dictionary<object,float>Dictionary<object,int>等与后备Dictionary<object,object>以及许多SetValue函数一起使用,因此现在我不要在插入时进行包装。但是,由于GetValue函数来自接口(interface),因此我无法对其施加约束,因此我仍然在退出时进行装箱:
T GetValue<T>(object key) {
    if (typeof(T) == typeof(int)) {
        // return intStore[key]; // doesn't compile
        return (T)(object)intStore[key]; // boxes, allocates, bad.
    }
    // ...
}

我在这里缺少语法技巧,包括更改黑板界面,以避免拳击吗?即使您无需分配也可以实现“反射”,但任何反射黑客都将违反“快速”要求。

干杯。

最佳答案

虽然我不想这样做(并且我需要说服装箱的成本确实会很大),但是您可以拥有多个商店,并且在您的方法中具有Dictionary<object, T>类型的变量-这样,我相信您应该避免装箱:

T GetValue<T>(object key)
{
    Dictionary<object, T> store;
    if (typeof(T) == typeof(int)
    {
         store = (Dictionary<object, T>) (object) intStore;
    }
    else if (typeof(T) == typeof(float))
    {
        store = (Dictionary<object, T>) (object) floatStore;
    }

    // etc - with a default or an error case for unhandled types.
    return store[key];
}

请注意,此处进行两次强制转换是使编译器保持满意的必要条件,但它不涉及装箱。

10-06 12:53