很奇怪,这是我第一次遇到这个问题,但是:

如何在c#接口中定义构造函数?

编辑 有些人想要一个例子(这是一个自由时间项目,所以是的,这是一个游戏)

IDrawable +更新 +画

为了能够更新(检查屏幕边缘等)和绘制本身,它总是需要一个GraphicsDeviceManager。我想确保对象有一个指向它的引用。这将属于构造函数。

现在我把这个写下来了,我想我在这里实现的是IObservable GraphicsDeviceManager应该采用IDrawable。 似乎不是我没有理解XNA框架,就是这个框架没有考虑得很好。

编辑 我在接口上下文中对构造函数的定义似乎有些混乱。接口确实不能被实例化,因此不需要构造函数。我想定义的是构造函数的签名。就像接口可以定义某个方法的签名一样,接口也可以定义构造函数的签名。


当前回答

创建一个定义构造函数的接口是不可能的,但可以定义一个接口,强制一个类型具有无参数构造函数,尽管它使用泛型的语法非常丑陋……实际上,我不太确定这是否是一种好的编码模式。

public interface IFoo<T> where T : new()
{
  void SomeMethod();
}

public class Foo : IFoo<Foo>
{
  // This will not compile
  public Foo(int x)
  {

  }

  #region ITest<Test> Members

  public void SomeMethod()
  {
    throw new NotImplementedException();
  }

  #endregion
}

另一方面,如果你想测试一个类型是否有无参数构造函数,你可以使用反射来做:

public static class TypeHelper
{
  public static bool HasParameterlessConstructor(Object o)
  {
    return HasParameterlessConstructor(o.GetType());
  }

  public static bool HasParameterlessConstructor(Type t)
  {
    // Usage: HasParameterlessConstructor(typeof(SomeType))
    return t.GetConstructor(new Type[0]) != null;
  }
}

希望这能有所帮助。

其他回答

通用工厂方法似乎仍然是理想的。您将知道工厂需要一个形参,而这些形参恰好被传递给正在实例化的对象的构造函数。

注意,这只是经过语法验证的伪代码,这里可能忽略了一个运行时警告:

public interface IDrawableFactory
{
    TDrawable GetDrawingObject<TDrawable>(GraphicsDeviceManager graphicsDeviceManager) 
              where TDrawable: class, IDrawable, new();
}

public class DrawableFactory : IDrawableFactory
{
    public TDrawable GetDrawingObject<TDrawable>(GraphicsDeviceManager graphicsDeviceManager) 
                     where TDrawable : class, IDrawable, new()
    {
        return (TDrawable) Activator
                .CreateInstance(typeof(TDrawable), 
                                graphicsDeviceManager);
    }

}

public class Draw : IDrawable
{
 //stub
}

public class Update : IDrawable {
    private readonly GraphicsDeviceManager _graphicsDeviceManager;

    public Update() { throw new NotImplementedException(); }

    public Update(GraphicsDeviceManager graphicsDeviceManager)
    {
        _graphicsDeviceManager = graphicsDeviceManager;
    }
}

public interface IDrawable
{
    //stub
}
public class GraphicsDeviceManager
{
    //stub
}

一个可能用法的例子:

    public void DoSomething()
    {
        var myUpdateObject = GetDrawingObject<Update>(new GraphicsDeviceManager());
        var myDrawObject = GetDrawingObject<Draw>(null);
    }

当然,您只需要通过工厂创建实例来保证始终有一个适当初始化的对象。也许使用像AutoFac这样的依赖注入框架会有意义;Update()可以向IoC容器“请求”一个新的GraphicsDeviceManager对象。

你不能。它偶尔会让人感到痛苦,但无论如何,使用正常的技术都无法调用它。

在一篇博客文章中,我建议静态接口只能在泛型类型约束中使用——但在我看来,它真的很方便。

如果你可以在一个接口中定义一个构造函数,那么你在派生类时就会遇到麻烦:

public class Foo : IParameterlessConstructor
{
    public Foo() // As per the interface
    {
    }
}

public class Bar : Foo
{
    // Yikes! We now don't have a parameterless constructor...
    public Bar(int x)
    {
    }
}

强制某种构造函数的一种方法是在接口中只声明getter,这可能意味着实现类必须有一个方法,最好是一个构造函数,为它设置(私有的)值。

我回头看这个问题,心想,也许我们处理这个问题的方法是错误的。当涉及到定义带有特定参数的构造函数时,接口可能不是正确的方法……但是(抽象的)基类是。

如果在基类上创建一个构造函数,该构造函数接受所需的参数,则从基类派生的每个类都需要提供这些参数。

public abstract class Foo
{
  protected Foo(SomeParameter x)
  {
    this.X = x;
  }

  public SomeParameter X { get; private set }
}

public class Bar : Foo // Bar inherits from Foo
{
  public Bar() 
    : base(new SomeParameter("etc...")) // Bar will need to supply the constructor param
  {
  }
}

你不能。

接口定义了由其他对象实现的契约,因此不需要初始化状态。

如果需要初始化某些状态,则应该考虑使用抽象基类。