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

本文关键字:有效 接口 实现 有可能 定义 是否 | 更新日期: 2023-09-27 18:15:30

我已经思考这个问题好几天了:
是否有可能定义有效的c#接口,不能以任何方式实现?

这个问题的可能变体:是否有可能在 c# 2.0, 3.0, 4.0, 5.0中定义这样的接口?是否有可能定义这样的接口,即使在实现时也不会编译,或者可以编译但会抛出运行时异常?

编辑:我知道这样的接口仅仅从定义上来说是无用的,但是对于讲座或测试编程工作申请人对c#的了解程度来说,这是一个很好的答案。

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

是否可以定义不能实现的有效c#接口?

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

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

IFoo<T>不能被任何T实现,因为没有类型参数可以代替TC不能工作,因为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#编译器规范中添加类似的语言,但还没有付诸实施。使用这些类型会导致编译器或运行时崩溃。

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

走向无限但不超越


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

interface ΙAmAPerfectlyOrdinaryInterface { }

class C : IAmAPerfectlyOrdinaryInterface { }

既然我们在谈论琐事,我认为这是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> { }

它可以很好地编译,但是当实例化D时,StackOverflowException会崩溃。

如果你试图找出一个旧的接口,你可以用ObsoleteAttribute属性标记接口。

编辑:作为@Magnus在评论中注意到,如果你将Error属性设置为true,它的使用将导致错误。

如果一个类型是可访问且未密封的,那么外部代码就有可能创建该类型的实例,并且基类型对此无能为力。不需要"完全信任"或反射。

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#以外的语言编写的代码将允许对Finalize的重写退出,而不链接到它的父类。

我认为有可能用struct和类约束的组合来指定一个开放的泛型接口,这是任何类型的组合都无法实现的,例如

public interface evil<T, U>
    where T : struct,U
    where U : class

我不确定这样的开放泛型类型是否真的符合"接口"的条件,或者只有封闭泛型类型才能真正符合接口(或类,或结构)的条件。