我试图将以下C#代码转换为D,但是我不知道如何使模板约束起作用。
C#实现
public interface IComponent
{
}
public class Container
{
public T CreateComponent<T>() where T: IComponent, new()
{
// Trivial initialisation for example
var t = new T();
return t;
}
}
D实施
public interface Component
{
}
public class Container
{
public T createComponent(T)()
{
// Trivial initialisation for example
auto t = new T();
return t;
}
}
如何重新创建“where T:IComponent”约束?
我试过各种表达式结合is,typeof等,但是找不到任何有效的方法。
最佳答案
好吧,如果您要做的只是要求T
实现IComponent
接口,那么is(T : IComponent)
将测试T
可隐式转换为IComponent
(在IComponent
是T
的基类或它实现的接口的情况下) 。因此,您最终会得到类似
public class Container
{
public T createComponent(T)()
if(is(T : IComponent))
{
// Trivial initialisation for example
auto t = new T();
return t;
}
}
现在,从技术上讲,如果使用
alias this
定义隐式转换,则其他东西可以匹配,这不太常见,但是如果您对此抱有偏执,则可以使约束条件也检查T
是否为类- is(T == class)
。public class Container
{
public T createComponent(T)()
if(is(T == class) && is(T : IComponent))
{
// Trivial initialisation for example
auto t = new T();
return t;
}
}
然后,
T
必须是一个类,并且必须隐式转换为IComponent
。但是,从技术上讲,T
仍然是不实现IComponent
的类,但确实定义了一个alias this
可以转换为IComponent
的类(T
不再是可以做到这一点的结构)。因此,这并不完美,但是我不知道一种方法来确保通过继承而不是alias this
进行隐式转换。因此,不幸的是,我不知道一种绝对保证T
是实现IComponent
的类的方法。我所知道的最大方法是确保它隐式转换为`IComponent,这几乎总是意味着它实现了它。但是,实际情况是,在大多数情况下,仅检查
is(T : IComponent)
就足够了,并且取决于您的代码编写方式,它甚至可以与隐式转换为IComponent
但实际上不是IComponent
的类型一起使用。因此,alias this
在工作中抛出扳手这一事实实际上可能不是问题。但是,一般而言,alias this
是通用代码的祸根,为什么大多数通用代码不应该检查隐式转换。对于类型而言,通过alias this
隐式转换但实际上并未在函数中进行转换太容易了,在这种情况下,它要么无法编译,要么如果它支持与目标类型相同的操作,则它可能具有奇怪的行为,但是这些操作的结果与原始类型实际转换为目标类型的结果不同。因此,如果您实际上希望在模板代码中进行隐式转换,则应通过将参数分配给目标类型来强制进行隐式转换。但是由于您通常是在测试接口而不是隐式转换,因此您可能需要的是一种测试该接口而不允许通过alias this
进行隐式转换的测试。不幸的是,我知道在编译时检查一种类型是从另一个类型派生还是实现特定接口的唯一方法是检查它是否隐式转换为该基类或接口。但是也许有一些有趣的具有特征的伏都教实际上可以做到。如果有的话,我们应该在std.traits中添加一些可以为您完成的工作,如果没有,也许我们应该找到一种添加方法,因为如果您不想要
alias this
的话,肯定会很烦人。但是幸运的是,这不是大多数代码中出现的问题,并且,如果您不编写公共API,则只需用alias this
声明类型就不必担心。如果不是,那真的没关系。