我有一个泛型类Proxy<T>
,我想编写另一个泛型类,其类型参数是代理。
我想写:
public class MyClass<U> where U : Proxy<T>
但编译器会报告The type or namespace name T could not be found
。
我发现的一个解决方案就是声明它:
public class MyClass<U, T> where U : Proxy<T>
但这似乎很笨拙,因为客户端必须声明两个类型参数,如:
public class SomeClass { ... }
public class SomeProxy : Proxy<SomeClass> { ... }
然后在某个客户端:
var proxyWrapper = new MyClass<SomeProxy, SomeClass>();
如何在MyClass
上无需两个泛型类型的情况下执行此操作。毕竟,如果我们知道第一个是SomeProxy
,则应该遵循第二个SomeClass
。
答案 0 :(得分:2)
也许这样的事情也可以完成这项工作?
class Test<T> {
public Test(Proxy<T> proxy) { this.MyProxy = proxy; }
public Proxy<T> MyProxy { get; private set; }
}
答案 1 :(得分:1)
您可以拥有一个接口IMyClass<SomeProxy>
和一个工厂方法,用于创建并返回MyClass<SomeProxy, SomeClass>
的实例。您可能需要使用Reflection创建实例。
我有类似情况的代码示例here:最终用户只关心单个类型参数,但实现需要有两个。在我的示例中,我不必使用Reflection来创建实例,但听起来您可能需要这样做。
您正在尝试使用C ++模板等编译时构造,而不是C#泛型等运行时构造。
答案 2 :(得分:1)
抱歉,如果两种类型都没有MyClass
泛型,你就无法在C#中执行此操作(除非您想使用反射来创建它的实例。)
答案 3 :(得分:0)
如果您希望T在Myclass
中保持通用,那么MyClass
实例仍然需要解析所有内部使用的泛型类型,并且您必须在某处声明它。要走的路是你提到的冗长方式:
public class MyClass<U, T> where U : Proxy<T>
如果您不关心T
中的泛型类型MyClass
,请创建界面并改为使用它:
public interface IProxy { ... }
public class SomeClass { ... }
public class SomeProxy : Proxy<SomeClass>, IProxy { ... }
public class MyClass<U> where U : IProxy
然后在某个客户端:
var proxyWrapper = new MyClass<SomeProxy>();
但请注意,您不能在接口声明中使用类型T,而类型U现在更加通用。
答案 4 :(得分:0)
事实证明,我想要处理的所有SomeProxy
类实际上只是覆盖了一个具有签名的Proxy<T>
方法:
T LoadInternal(Identifier id)
所以,我所做的是在MyClass中创建了一个内部类,它的构造函数中包含Func<Identifier, T>
。然后我可以将Func<Identifier, T>
作为参数传递给MyClass的构造函数,并使用我的子类代替SomeProxy。
似乎有点令人费解,但它对我有用。总而言之,我现在有:
public class MyClass<T>{
private SomeProxy theProxy;
public MyClass(Func<Identifier, T> loadDelegate){
theProxy = new SomeProxy(loadDelegate);
}
/* Other methods here */
class SomeProxy : Proxy<T>{
private Func<Identifier, T> m_loadInternal;
public SomeProxy(Func<Identifier, T> loadInternal){
m_loadInternal = loadInternal;
}
protected override T LoadInternal(Identifier id){
return m_loadInternal(id);
}
}
}
因此,从客户端代码开始,我只使用以下方法创建MyClass,而不是编写一个扩展Proxy然后覆盖该类的LoadInternal的类。
var myClass = new MyClass<T>(x => CodeWhichReturnsT());
答案 5 :(得分:0)
如何在MyClass上不必拥有两个泛型类型的情况下执行此操作。毕竟,如果我们知道第一个是SomeProxy,那么应该遵循第二个是SomeClass。
虽然你似乎找到了问题主要部分的答案,但我想我会提供对这一部分的理解。听起来你希望你能做到这样的事情:
class Proxy<T>
{
T Value { get; set; }
}
class MyClass<U> where U : Proxy<> { }
并在您提供Proxy
时让编译器填写U
类型参数。由于您已声明U继承自Proxy,因此您必须打算使用Proxy上的一个方法,这可能使用T参数,如下所示:
class MyClass<U> where U : Proxy<>
{
void SomeMethod(U parameter)
{
var local = parameter.Value;
//more code here...
}
}
现在,编译器应该在这里为local
推断出什么?这是我看到的主要问题,如果可能的话,很难实现这样的功能。如果您不想使用任何使用泛型类型的Proxy的方法,您可以改为创建非泛型基类并将其用于U
并回避整个问题。
我不是编译器编写者,但想到如何解决这个问题的几种可能性。它可以说对象(或者你在代理中对类型参数施加的任何其他限制),但这似乎不太正确或者正常的泛型似乎做的事情。这也需要CLR允许打开泛型类型作为泛型参数的约束,我怀疑它是否存在。我能看到的另一个选项是类型实际上有第二个类型参数,编译器为你提供语法糖,使其更容易。
无论你走到哪里,这个功能似乎都可以在很少的情况下获得一些好处,因此不太可能实现切割。