C# 中的抽象显式接口实现

Posted

技术标签:

【中文标题】C# 中的抽象显式接口实现【英文标题】:abstract explicit interface implementation in C# 【发布时间】:2010-10-22 03:50:59 【问题描述】:

我有这个 C# 代码:

abstract class MyList : IEnumerable<T>

    public abstract IEnumerator<T> GetEnumerator();

    //abstract IEnumerator IEnumerable.GetEnumerator();

按原样,我得到:

'Type' 没有实现接口成员'System.Collections.IEnumerable.GetEnumerator()'。

删除评论,我得到:

修饰符“抽象”对此项无效

如何制作显式的实现抽象

【问题讨论】:

这是 C# 编译器恕我直言的一个缺点。在许多用例中,您必须“仅仅因为”添加一个虚拟实现。此外,如果您选择非抽象成员,编译器将允许没有实现的子类,从而暴露调用虚拟实现的风险。 【参考方案1】:

有趣 - 我不确定你能做到。但是,如果这是您的真实代码,您是否想以任何方式实现非泛型 GetEnumerator(),而不是通过调用泛型的方式其他

我会这样做:

abstract class MyList<T> : IEnumerable<T>

    public abstract IEnumerator<T> GetEnumerator();

    IEnumerator IEnumerable.GetEnumerator() 
    
        return GetEnumerator();
    

这使您免于在每个派生类中实现它的繁琐——毫无疑问,所有派生类都使用相同的实现。

【讨论】:

我没有理由认为它会以任何其他方式实现......但你永远不知道。 +1 重新发表您的评论 - 我可能误读了它...已编辑以修复它,并发现代码与您的相同 - 因此已删除;-p【参考方案2】:

虽然显式接口成员可能不是抽象(或虚拟)成员,但它可以根据抽象(或虚拟)成员来实现1

public abstract class Foo: IEnumerable 
    IEnumerator IEnumerable.GetEnumerator()  
        return getEnumerator();    
    

    protected abstract IEnumerator getEnumerator(); 


public class Foo<T>: Foo, IEnumerable<T> 
    private IEnumerable<T> ie;
    public Foo(IEnumerable<T> ie) 
        this.ie = ie;
    

    public IEnumerator<T> GetEnumerator() 
        return ie.GetEnumerator();
    

    protected override IEnumerator getEnumerator() 
        return GetEnumerator();
    

    //explicit IEnumerable.GetEnumerator() is "inherited"

我发现在强类型 ASP.NET MVC 3 部分视图中需要这样做,它不支持泛型类型定义模型(据我所知)。

【讨论】:

我发现自己也不得不使用这个解决方案。谢谢! (Jon Skeets 的回答在提供的示例中是有道理的,但如果没有这种简单的关系,据我所知,这似乎是最明智的解决方案。) 谢谢。这样你也可以实现一种内部接口方法。如果接口是内部的,抽象方法也是内部的。【参考方案3】:

您实际上可以做到这一点,方法是强制派生自抽象类的类实现接口,并仍然允许它选择如何实现该接口 - 隐式或显式:

namespace Test

    public interface IBase<T>
    
        void Foo();
    

    public abstract class BaseClass<T> 
        where T : IBase<T>  // Forcing T to derive from IBase<T>
     

    public class Sample : BaseClass<Sample>, IBase<Sample>
    
        void IBase<Sample>.Foo()  
    

    class Program
    
        static void Main(string[] args)
        
            Sample sample = new Sample();

            // Error CS1061  'Sample' does not contain a definition for 'Foo' 
            // and no extension method 'Foo' accepting a first argument of type 'Sample' 
            // could be found(are you missing a using directive or an assembly reference ?)
            sample.Foo();

            (sample as IBase<Sample>).Foo(); // No Error
        
    

【讨论】:

这是一个“好奇者和好奇者”模式。现在您可以添加: public class Sample2 : BaseClass, IBase 这并没有真正做到你期望它做的事情。它基本上是在说明 Base 其中 T : Base 它可以是任何 Base。例如。 X : Base 和 Y : Base【参考方案4】:

我有一个稍微复杂的案例,我希望基类显式实现非泛型接口,派生类实现泛型接口。

接口:

public interface IIdentifiable<TKey> : IIdentifiable

    TKey Id  get; 


public interface IIdentifiable

    object Id  get; 

我通过在基类中声明一个抽象 getter 方法并让显式实现调用它来解决它:

public abstract class ModelBase : IIdentifiable

    object IIdentifiable.Id
    
        get  return GetId();  
    

    protected abstract object GetId();


public class Product : ModelBase, IIdentifiable<int>

    public int ProductID  get; set; 

    public int Id
    
        get  return ProductID; 
    

    protected override object GetId()
    
        return Id;
    

请注意,基类没有它可以调用的Id 的类型化版本。

【讨论】:

【参考方案5】:

似乎不可能做一个抽象的显式接口实现,但你可以做一个解决方法来摆脱错误,但仍然强制使用隐式的显式接口实现:

abstract class MyList : IEnumerable<T>

    public virtual IEnumerator<T> GetEnumerator() 
        (this as IEnumerable).GetEnumerator();
    

但是,正如对上述问题的评论所指出的那样:

如果您选择非抽象成员,编译器将允许没有(自己的)实现的子类...

【讨论】:

以上是关于C# 中的抽象显式接口实现的主要内容,如果未能解决你的问题,请参考以下文章

C#接口的隐式和显式实现

C# - 接口_显式接口实现

C# 显式接口成员实现

在 C# 中实现接口与显式实现接口 [重复]

C#:在实现的方法中显式指定接口

C#接口的隐式和显式实现之间的区别[重复]