是否可以定义无法实现的有效C#接口?

时间:2013-05-27 19:33:54

标签: c# interface

我已经考虑了这个(meta)问题几天了:
是否可以定义无法以任何方式实现的有效C#接口?

此问题的可能变体:是否可以在 C#2.0,3.0,4.0,5.0 中定义此类界面?是否有可能定义在实现时甚至不编译的接口,或者可以编译但抛出运行时异常的接口?

编辑:我知道这样的界面只是按照定义无用,但对于编程工作的演讲或测试申请人来说,他们对C#的了解有多好,这是一个很好的答案。

4 个答案:

答案 0 :(得分:17)

  

是否可以定义无法实现的有效C#接口?

这个琐事问题不适合StackOverflow,但是很简单,很容易回答。 (错误的是,事实证明!继续阅读!)

class C
{
    private C() {}
}
interface IFoo<T> where T : C, new()
{
}
无法为任何IFoo<T>实施

T,因为没有可替代T的类型参数。 C不起作用,因为C没有公共无参数构造函数,并且没有C的派生类,因为默认构造函数是私有的。 (好吧,C内可能有C的可访问派生类,但在这种情况下不存在。)


更新:评论者“mike z”正确指出

class X<T> : IFoo<T> where T : C, new() {}

实现了接口,当然现在没有办法实例化X<T>

更好的是,用户“GranBurguesa”指出允许声明派生类C,只要它从不调用私有构造函数;这只有在实例化时崩溃并死亡时才有可能。 (好吧,为了挑剔,也可以将递归调用优化到无限循环而不是崩溃。)

两种狡猾的解决方法都提出了一个哲学问题:如果一个接口是由一个没有人可以实例化的类实现的,它是否真的实现了?当然,GranBurguesa证明IFoo<D>可以实现和构建,所以我的答案实际上是错误的。


还有一些案例,例如在SLaks删除的答案中暗示的案例,其中滥用通用机制导致“无限”类型。这些类型在CLR中是不合法的; C#设计团队已经考虑过为C#编译器规范添加类似的语言,但尚未解决它。使用这些类型可能会使编译器或运行时崩溃。

有关使编译器崩溃的无限类型的示例,请参阅我的文章:

To Infinity But Not Beyond


这是一个。将此代码剪切并粘贴到Visual Studio中,您将看到无法实现此接口:

interface ΙAmAPerfectlyOrdinaryInterface { }

class C : IAmAPerfectlyOrdinaryInterface { }

答案 1 :(得分:9)

只要我们谈论琐事,我认为这是Eric Lippert尝试的有效实施:

class Program
{
    static void Main(string[] args)
    {
        D test = new D();
    }
}

class C
{
    private C() { }
}

interface IFoo<T> where T : C, new() { }

class D : C
{
    public D()
        : this(5) { }

    public D(int x)
        : this() { }
}

class Dfoo : IFoo<D> { }

当您实例化StackOverflowException时,它会很好地编译但会导致D崩溃。

答案 2 :(得分:7)

如果您尝试分解旧界面,可以使用ObsoleteAttribute属性标记界面。

编辑,因为 @Magnus 在评论中注明,如果您设置Error attribute to true,它的使用会导致错误。

答案 3 :(得分:5)

如果一个类型是可访问和未密封的,那么外部代码可以创建该类型的实例,并且基本类型无法对其进行任何操作。没有&#34;完全信任&#34;或需要反思。

public class CantDeriveMe
{
    private CantDeriveMe()
    {
    }
    public override string ToString()
    {
        return "My type is " + this.GetType().ToString();
    }
}

public class OhYeah : CantDeriveMe
{
    static OhYeah CapturedInstance;

    ~OhYeah()
    {
        CapturedInstance = this;
    }

    OhYeah() : this(1/String.Empty.Length)
    {
    }
    OhYeah(int blah) : this()
    {
    }
    public static OhYeah Create()
    {
        try
        {
            new OhYeah(4);
        }
        catch (DivideByZeroException)
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
        return CapturedInstance;
    }
    public static void test()
    {
        OhYeah it;
        it = OhYeah.Create();
        Console.WriteLine("Result was ({0})", it);
    }
}

请注意,如果代码仅在C#中编写,则基类析构函数可能会发出声音,如果它注意到该对象不是合法类型,但使用C#以外的语言编写的代码将允许覆盖{ {1}}退出而不链接到其父级。

我认为可以指定一个开放的通用接口,其中包含Finalize和类约束的组合,没有类型的组合可能实现,例如。

struct

我不确定这样的开放泛型类型是否真的有资格作为&#34;接口&#34;,或者是否只有封闭的泛型类型才真正有资格作为接口(或类或结构) )。