C# 定义构造函数签名的接口?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/619856/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 10:32:39  来源:igfitidea点击:

Interface defining a constructor signature?

c#interfaceconstructor

提问by Boris Callens

It's weird that this is the first time I've bumped into this problem, but:

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

How do you define a constructor in a C# interface?

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

Edit
Some people wanted an example (it's a free time project, so yes, it's a game)

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

IDrawable
+Update
+Draw

IDrawable
+Update
+Draw

To be able to Update (check for edge of screen etc) and draw itself it will always need a GraphicsDeviceManager. So I want to make sure the object has a reference to it. This would belong in the constructor.

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

Now that I wrote this down I think what I'm implementing here is IObservableand the GraphicsDeviceManagershould take the IDrawable... It seems either I don't get the XNA framework, or the framework is not thought out very well.

既然我写下了这个,我想我在这里实现的是IObservable并且GraphicsDeviceManager应该采用IDrawable......似乎我没有得到 XNA 框架,或者框架没有考虑得很好。

Edit
There seems to be some confusion about my definition of constructor in the context of an interface. An interface can indeed not be instantiated so doesn't need a constructor. What I wanted to define was a signature to a constructor. Exactly like an interface can define a signature of a certain method, the interface could define the signature of a constructor.

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

采纳答案by Dan

As already well noted, you can't have constructors on an Interface. But since this is such a highly ranked result in Google some 7 years later, I thought I would chip in here - specifically to show how you could use an abstract base class in tandem with your existing Interface and maybe cut down on the amount of refactoring needed in the future for similar situations. This concept has already been hinted at in some of the comments but I thought it would be worth showing how to actually do it.

如前所述,您不能在接口上拥有构造函数。但由于大约 7 年后,这在 Google 中排名如此靠前,我想我会在这里插手 - 特别是展示如何将抽象基类与现有接口结合使用,并可能减少重构的数量以后类似情况需要。一些评论中已经暗示了这个概念,但我认为值得展示如何实际做到这一点。

So you have your main interface that looks like this so far:

到目前为止,您的主界面如下所示:

public interface IDrawable
{
    void Update();
    void Draw();
}

Now create an abstract class with the constructor you want to enforce. Actually, since it's now available since the time you wrote your original question, we can get a little fancy here and use generics in this situation so that we can adapt this to other interfaces that might need the same functionality but have different constructor requirements:

现在使用您要强制执行的构造函数创建一个抽象类。实际上,由于自您编写原始问题以来它现在可用,因此我们可以在这里稍微花哨并在这种情况下使用泛型,以便我们可以将其调整为可能需要相同功能但具有不同构造函数要求的其他接口:

public abstract class MustInitialize<T>
{
    public MustInitialize(T parameters)
    {

    }
}

Now you'll need to create a new class that inherits from both the IDrawable interface and the MustInitialize abstract class:

现在您需要创建一个继承自 IDrawable 接口和 MustInitialize 抽象类的新类:

public class Drawable : MustInitialize<GraphicsDeviceManager>, IDrawable
{
    GraphicsDeviceManager _graphicsDeviceManager;

    public Drawable(GraphicsDeviceManager graphicsDeviceManager)
        : base (graphicsDeviceManager)
    {
        _graphicsDeviceManager = graphicsDeviceManager;
    }

    public void Update()
    {
        //use _graphicsDeviceManager here to do whatever
    }

    public void Draw()
    {
        //use _graphicsDeviceManager here to do whatever
    }
}

Then just create an instance of Drawable and you're good to go:

然后只需创建一个 Drawable 实例就可以了:

IDrawable drawableService = new Drawable(myGraphicsDeviceManager);

The cool thing here is that the new Drawable class we created still behaves just like what we would expect from an IDrawable.

这里很酷的一点是,我们创建的新 Drawable 类的行为仍然与我们对 IDrawable 的期望一样。

If you need to pass more than one parameter to the MustInitialize constructor, you can create a class that defines properties for all of the fields you'll need to pass in.

如果您需要将多个参数传递给 MustInitialize 构造函数,您可以创建一个类,为您需要传入的所有字段定义属性。

回答by Jon Skeet

You can't. It's occasionally a pain, but you wouldn't be able to call it using normal techniques anyway.

你不能。偶尔会很痛苦,但无论如何您都无法使用正常技术调用它。

In a blog post I've suggested static interfaceswhich would only be usable in generic type constraints - but could be really handy, IMO.

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

One point about if you coulddefine a constructor within an interface, you'd have trouble deriving classes:

关于如果您可以在接口中定义构造函数的一点,您将无法派生类:

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)
    {
    }
}

回答by Michael

You can't.

你不能。

Interfaces define contracts that other objects implement and therefore have no state that needs to be initialized.

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

If you have some state that needs to be initialized, you should consider using an abstract base class instead.

如果您有一些需要初始化的状态,您应该考虑使用抽象基类。

回答by royatl

you don't.

你没有。

the constructor is part of the class that can implement an interface. The interface is just a contract of methods the class must implement.

构造函数是可以实现接口的类的一部分。接口只是类必须实现的方法的契约。

回答by Jeroen Landheer

It is not possible to create an interface that defines constructors, but it ispossible to define an interface that forces a type to have a paramerterless constructor, though be it a very ugly syntax that uses generics... I am actually not so sure that it is really a good coding pattern.

这是不可能创建一个接口,定义构造函数,但它可以定义一个接口,部队类型有paramerterless构造,但无论是非常难看的语法使用泛型......我其实没有那么肯定这确实是一个很好的编码模式。

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
}

On the other hand, if you want to test if a type has a paramerterless constructor, you can do that using reflection:

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

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;
  }
}

Hope this helps.

希望这可以帮助。

回答by Gert Arnold

A very late contribution demonstrating another problem with interfaced constructors. (I choose this question because it has the clearest articulation of the problem). Suppose we could have:

一个非常晚的贡献,展示了接口构造函数的另一个问题。(我选择这个问题是因为它对问题有最清晰的表达)。假设我们可以:

interface IPerson
{
    IPerson(string name);
}

interface ICustomer
{
    ICustomer(DateTime registrationDate);
}

class Person : IPerson, ICustomer
{
    Person(string name) { }
    Person(DateTime registrationDate) { }
}

Where by convention the implementation of the "interface constructor" is replaced by the type name.

按照惯例,“接口构造函数”的实现由类型名称替换。

Now make an instance:

现在做一个实例:

ICustomer a = new Person("Ernie");

Would we say that the contract ICustomeris obeyed?

我们会说合同ICustomer得到遵守吗?

And what about this:

这又如何呢:

interface ICustomer
{
    ICustomer(string address);
}

回答by Jeroen Landheer

I was looking back at this question and I thought to myself, maybe we are aproaching this problem the wrong way. Interfaces might not be the way to go when it concerns defining a constructor with certain parameters... but an (abstract) base class is.

我回头看这个问题,我心里想,也许我们处理这个问题的方式是错误的。当涉及定义具有某些参数的构造函数时,接口可能不是要走的路……但(抽象)基类是。

If you create a base class with a constructor on there that accepts the parameters you need, every class that derrives from it needs to supply them.

如果您创建一个带有构造函数的基类,该基类接受您需要的参数,那么从它派生的每个类都需要提供它们。

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
  {
  }
}

回答by Lea Hayes

It would be very useful if it were possible to define constructors in interfaces.

如果可以在接口中定义构造函数,那将非常有用。

Given that an interface is a contract that must be used in the specified way. The following approach might be a viable alternative for some scenarios:

鉴于接口是必须以指定方式使用的契约。对于某些情况,以下方法可能是可行的替代方案:

public interface IFoo {

    /// <summary>
    /// Initialize foo.
    /// </summary>
    /// <remarks>
    /// Classes that implement this interface must invoke this method from
    /// each of their constructors.
    /// </remarks>
    /// <exception cref="InvalidOperationException">
    /// Thrown when instance has already been initialized.
    /// </exception>
    void Initialize(int a);

}

public class ConcreteFoo : IFoo {

    private bool _init = false;

    public int b;

    // Obviously in this case a default value could be used for the
    // constructor argument; using overloads for purpose of example

    public ConcreteFoo() {
        Initialize(42);
    }

    public ConcreteFoo(int a) {
        Initialize(a);
    }

    public void Initialize(int a) {
        if (_init)
            throw new InvalidOperationException();
        _init = true;

        b = a;
    }

}

回答by Matthew

The generic factory approach still seems ideal. You would know that the factory requires a parameter, and it would just so happen that those parameters are passed along to the constructor of the object being instantiated.

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

Note, this is just syntax verified pseudo code, there may be a run-time caveat I'm missing here:

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

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
}

An example of possible usage:

一个可能的用法示例:

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

Granted, you'd only want the create instances via the factory to guarantee you always have an appropriately initialized object. Perhaps using a dependency injection framework like AutoFacwould make sense; Update() could "ask" the IoC container for a new GraphicsDeviceManager object.

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

回答by JTtheGeek

One way to solve this problem i found is to seperate out the construction into a seperate factory. For example I have an abstract class called IQueueItem, and I need a way to translate that object to and from another object (CloudQueueMessage). So on the interface IQueueItem i have -

我发现解决这个问题的一种方法是将建筑分离到一个单独的工厂中。例如,我有一个名为 IQueueItem 的抽象类,我需要一种方法来将该对象与另一个对象 (CloudQueueMessage) 相互转换。所以在接口 IQueueItem 我有 -

public interface IQueueItem
{
    CloudQueueMessage ToMessage();
}

Now, I also need a way for my actual queue class to translate a CloudQueueMessage back to a IQueueItem - ie the need for a static construction like IQueueItem objMessage = ItemType.FromMessage. Instead I defined another interface IQueueFactory -

现在,我还需要一种方法让我的实际队列类将 CloudQueueMessage 转换回 IQueueItem - 即需要像 IQueueItem objMessage = ItemType.FromMessage 这样的静态构造。相反,我定义了另一个接口 IQueueFactory -

public interface IQueueItemFactory<T> where T : IQueueItem
{
    T FromMessage(CloudQueueMessage objMessage);
}

Now I can finally write my generic queue class without the new() constraint which in my case was the main issue.

现在我终于可以在没有 new() 约束的情况下编写我的通用队列类,这在我的情况下是主要问题。

public class AzureQueue<T> where T : IQueueItem
{
    private IQueueItemFactory<T> _objFactory;
    public AzureQueue(IQueueItemFactory<T> objItemFactory)
    {
        _objFactory = objItemFactory;
    }


    public T GetNextItem(TimeSpan tsLease)
    {
        CloudQueueMessage objQueueMessage = _objQueue.GetMessage(tsLease);
        T objItem = _objFactory.FromMessage(objQueueMessage);
        return objItem;
    }
}

now I can create an instance that satisfies the criteria for me

现在我可以创建一个满足我的标准的实例

 AzureQueue<Job> objJobQueue = new JobQueue(new JobItemFactory())

hopefully this helps someone else out someday, obviously a lot of internal code removed to try to show the problem and solution

希望有一天这可以帮助其他人,显然删除了很多内部代码以尝试显示问题和解决方案

回答by ghord

You could do this with generics trick, but it still is vulnerable to what Jon Skeet wrote:

你可以用泛型技巧来做到这一点,但它仍然容易受到 Jon Skeet 所写的影响:

public interface IHasDefaultConstructor<T> where T : IHasDefaultConstructor<T>, new()
{
}

Class that implements this interface must have parameterless constructor:

实现此接口的类必须具有无参数构造函数:

public class A : IHasDefaultConstructor<A> //Notice A as generic parameter
{
    public A(int a) { } //compile time error
}