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

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

编辑

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

IDrawable

+更新

+绘制

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

现在我写下来了,我认为我在这里实现的是IObservable , GraphicsDeviceManager应该使用IDrawable ......似乎要么我没有得到XNA框架,要么框架没有考虑得很好。

编辑

关于我在接口上下文中对构造函数的定义似乎有些混乱。 实际上不能实例化接口,因此不需要构造函数。 我想要定义的是构造函数的签名。 正如接口可以定义某个方法的签名,接口可以定义构造函数的签名。

#1楼

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

鉴于接口是必须以指定方式使用的合同。 对于某些场景,以下方法可能是一种可行的替代方法:

public interface IFoo {
/// 
/// Initialize foo.
/// 
/// 
/// Classes that implement this interface must invoke this method from
/// each of their constructors.
/// 
/// 
/// Thrown when instance has already been initialized.
/// 
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;
}
}

#2楼

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

注意,这只是语法验证的伪代码,可能有一个运行时警告我在这里缺少:

public interface IDrawableFactory
{
TDrawable GetDrawingObject(GraphicsDeviceManager graphicsDeviceManager)
where TDrawable: class, IDrawable, new();
}
public class DrawableFactory : IDrawableFactory
{
public TDrawable GetDrawingObject(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(new GraphicsDeviceManager());
var myDrawObject = GetDrawingObject(null);
}

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

#3楼

我发现解决这个问题的一种方法是将建筑分隔成一个单独的工厂。 例如,我有一个名为IQueueItem的抽象类,我需要一种方法将该对象转换为另一个对象(CloudQueueMessage)。 所以在IQueueItem界面上我有 -

public interface IQueueItem
{
CloudQueueMessage ToMessage();
}

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

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

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

public class AzureQueue where T : IQueueItem
{
private IQueueItemFactory _objFactory;
public AzureQueue(IQueueItemFactory objItemFactory)
{
_objFactory = objItemFactory;
}
public T GetNextItem(TimeSpan tsLease)
{
CloudQueueMessage objQueueMessage = _objQueue.GetMessage(tsLease);
T objItem = _objFactory.FromMessage(objQueueMessage);
return objItem;
}
}

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

AzureQueue objJobQueue = new JobQueue(new JobItemFactory())

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

#4楼

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

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

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

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

#5楼

强制某种构造函数的一种方法是在接口中声明只有Getters ,这可能意味着实现类必须有一个方法,理想情况下是一个构造函数,以便为它设置值( private )。