【问题标题】:Can an interface define functions which discriminate based on the implementors class?接口可以定义基于实现者类进行区分的函数吗?
【发布时间】:2020-07-06 21:10:56
【问题描述】:

我正在尝试定义一个接口,该接口的函数只接受实现它的类类型。这是我目前所拥有的:

public interface ICombinableAction : IAction {
    public bool CombineActions(ICombinableAction toCombine);
}

public class MoveAllObjects : ICombinableAction {
    public bool CombineActions(ICombinableAction toCombine) {
        if (!(toCombine is MoveAllObjects)) {
            // This isn't possible, inform the caller
            return false;
        }
        ... // Combining logic
        return true;
    }
}

不幸的是,由于函数无法在编译时检查传入的对象的类型,我必须处理使用不兼容类的情况,然后在调用者中处理。

理想情况下,这可以通过定义接口来实现,使得只有同一个类的实例是可能的,类似于:

public interface ICombinableAction : IAction {
    public void CombineActions(Implementor toCombine);
}

public class MoveAllObjects : ICombinableAction {
    public void CombineActions(MoveAllObjects toCombine) {
        ... // Combining logic
    }
}

我怀疑这是不可能的,因为C# Interfaces: Is it possible to refer to the type that implements the interface within the interface itself? 中的答案。我怀疑这个问题Why C# doesn't allow inheritance of return type when implementing an Interface 也在绕开与我相同的问题。不过,这两个问题都没有帮助我找到针对我的特定问题的解决方案。

在这种情况下,什么是好的解决方案?

【问题讨论】:

    标签: c# .net interface


    【解决方案1】:

    如果我正确理解了您的问题 - 您可以使用泛型实现类似的目标:

    public interface ICombinableAction<T> where T : ICombinableAction<T>
    {
        public void CombineActions(T toCombine);
    }
    
    public class MoveAllObjects : ICombinableAction<MoveAllObjects>
    {
        public void CombineActions(MoveAllObjects toCombine)
        {
    
        }
    }
    

    【讨论】:

    • 此方法的一个潜在问题是,如果您想要一个 List&lt;ICombinableAction&lt;T&gt;&gt;,其中 T 对于您要放入列表中的一个或多个元素是不同的。
    • @JacobHuckins 是的,有效的观点,但这可以使用非通用版本的接口来解决。此外,如果 OP 想要编译时安全,那么这样的收集有多大意义?
    • 啊这看起来像我需要的。以前没有玩过泛型,我想我还有其他事情要调查!所以我确实有一个列表,但它是IActionICombinableAction 实现的)所以希望这应该意味着它可以正常工作。
    • 如果它必须引用基本类型,我不明白接口有什么好处。这没有按要求实现ICombinableAction,它实现了ICombinableAction&lt;MoveAllObjects&gt;。为什么要有接口?为什么不只拥有MoveAllObjects.CombineActions(MoveAllObjects)?我不明白这有什么作用。你能举一个使用例子吗?特别是你能演示在不命名基类的情况下命名协变接口所需的参数协变吗?
    • @Malrig 看来您只需将检查添加到接口bool CombinableWith(ICombinableAction other) 并且不要打扰泛型。
    猜你喜欢
    • 1970-01-01
    • 2018-02-08
    • 1970-01-01
    • 2019-06-06
    • 1970-01-01
    • 2011-06-15
    • 1970-01-01
    • 2018-05-10
    • 1970-01-01
    相关资源
    最近更新 更多