如何让公共类从私有接口继承,而不会出现不一致的可访问性错误

时间:2015-02-24 19:29:53

标签: c# generics types constraints

这是对我想做的事情的解释:

public class MyClass
{
  public T GetFoo<T>() : where T : class, MyInterface
  {
    if (typeof(T) == typeof(Class1)
    {
      return new Class1() as T;
    }
    else if (typeof(T) == typeof(Class2))
    {
      return new Class2() as T;
    }
    else
    {
      return default(T);
    }
  }

  private interface MyInterface {}  // This is actually empty, it doesn't do anything except limit the types that can be passed to GetFoo()

  public class Class1 : MyInterface
  {
    // Stuff
  }

  public class Class2 : MyInterface
  {
    // Other Stuff
  }
  // there are many more such classes that all inherit from MyInterface
}

所以,我有一个带公共方法的公共课。该方法接受泛型类型参数。但我想限制它接受的T的类型,这就是为什么它使用MyInterface。 当然,由于MyInterface是私有的,因此无法编译。它抛出了“不一致的可访问性:约束类型比”错误更容易访问。

但这就是为什么我希望它以这种方式工作:

Class1,Class2等中的每一个都被声明为public,以便其他人可以使用它们。但是我想限制其他人声明他们自己的类并将它们传递给GetFoo()方法。因为这会破坏GetFoo(),所以我希望MyInterface是私有的。

如果我将MyInterface公开,当然它会编译,一切都会正常工作。但我需要能够阻止其他人声明自己的类并继承MyInterface并将其传递给GetFoo()。

我想允许来电者这样做:

Class1 userFoo = GetFoo<Class1>();

我想阻止来电者这样做:

Class UserClass : MyInterface {}
...
UserClass userFoo = GetFoo<UserClass>();

编辑:感谢所有非常快速的回复。是的,我知道这不是Interface的目的,当时对我来说似乎有意义。如果存在,我当然愿意接受更优雅的解决方案。

3 个答案:

答案 0 :(得分:2)

你做不到。这基本上是不可能的。通过创建接口private,调用者实际上不知道类是否实现了该接口。但是通过在类型约束中使用它,您需要调用者知道类是否实现了该接口。


你可以做的是使用一个共同的基类:即使该类必须是public,你也可以阻止其他类派生它。

public class Base {
  internal Base() { }
}
public interface IBase { }
public sealed class Class1 : Base, IBase {
  ...
}
public sealed class Class2 : Base, IBase {
  ...
}
public T GetFoo<T>() where T : Base, IBase {
  ...
}

IBase界面是为了确保GetFoo<Base>被拒绝。 Class1Class2sealed,以防止他人从中获取。

但是,只有Class1Class2应该具有公共基类时,此方法才有效。


我鼓励重新考虑你的设计。几乎总是,如果您的通用代码有一堆typeof(T) == typeof(SomeConcreteClass)条件,那么这表明您最好为每种具体类型创建单独的方法。但也有例外,我不排除您的代码成为例外的可能性。

答案 1 :(得分:0)

创建一个实现接口的类并尝试隐藏接口为您提供的抽象是完全没有意义的。

OO不是关于对象的编程,你肯定要做的,而是关于接口编程,你试图隐藏它们。

更好地考虑不同的方法。

答案 2 :(得分:-1)

此代码可以运行并编译:

public class MyClass<T> where T : class, IMyInterface
{
    public T GetFoo()
    {
        if (typeof (T) == typeof (Class1))
        {
            return new Class1() as T;
        }
        else if (typeof (T) == typeof (Class2))
        {
            return new Class2() as T;
        }
        else
        {
            return default(T);
        }
    }
}

public interface IMyInterface {}  // This is actually empty, it doesn't do anything except limit the types that can be passed to GetFoo()

public class Class1 : IMyInterface
{
// Stuff
}

public class Class2 : IMyInterface
{
// Other Stuff
}
// there are many more such classes that all inherit from MyInterface

主要方法很好:

    static void Main(string[] args)
    {
        var a1 = new MyClass<Class1>();
        var a2 = a1.GetFoo();
    }