比如说我有这个基类
class Mangler<TInput, TOutput>
{
}
然后我制作了几个派生类
class StringToBytesMangler : Mangler<string, byte[]>
{
}
class IntToGuidMangler : Mangler<int, Guid>
{
}
如何存储Mangler<TInput, TOutput>
的集合TInput
和TOutput
在任何给定时间可能不同?
即
List<Mangler<?, ?>> list = new List<Mangler<?, ?>>();
list.Add(new StringToBytesMangler());
list.Add(new IntToGuidMangler());
这可能吗?
答案 0 :(得分:2)
您需要一个非通用的Mangler
基类。
List<Mangler> list = new List<Mangler>();
list.Add(new StringToBytesMangler());
list.Add(new IntToGuidMangler());
当然,这意味着您还需要拥有依赖TInput
或TOutput
的方法的非通用版本。
答案 1 :(得分:2)
如果我正确理解了这个问题,那就不可能按照你的方式进行。 StringToBytesMangler
和IntToGuidMangler
类型不来自同一类型。您可以引入共享基类型,但我建议重新考虑设计 - 即使它们可以存储在同一个集合中,它们在语法上也没有任何共同之处(至少它没有在问题中显示)。
答案 2 :(得分:0)
泛型背后的整个想法是拥有通用代码,因此该类的类型可以被视为相同。根据您发布的内容,您很难看到您拥有的通用代码。
下面我有一个包含通用代码的类:
class Mangler<TInput, TOutput>
where TInput: ITInput
where TOutput: ITOutput {
public TInput Input { get; set; }
public TOutput Output { get; set; }
public bool IsInputAGuid() {
if (Guid.Parse(this.Input.SomeThing) == this.Output.SomeGuid ) {
return true;
}
return false;
}
}
您可以在上面的类中看到,当它从Guid
将字符串解析为this.Input.Something
,然后使用==
对其执行this.Ouput.SomeGuid
时,编译器是很高兴,因为我们已经制定了TInput
必须实现接口ITInput
的约束,因此编译器知道此行将起作用,而Input
将Something
作为string
属性:
Guid.Parse(this.Input.SomeThing)
只要Something
可用,编译器就不关心具体类型是什么。 TOuput
的想法是一样的,但编译器希望它实现ITOutput
,因此它需要Guid
中的SomeGuid
。这就是为什么编译器很乐意将字符串解析为guid,然后使用另一个也是==
的东西对其执行Guid
运算符。
以下是接口和一些实现它们的类:
internal interface ITInput {
string SomeThing { get; set; }
}
internal interface ITOutput {
Guid SomeGuid { get; set; }
}
internal class AnotherInput : ITInput {
public string SomeThing { get; set; }
}
internal class SomeInput : ITInput {
public string SomeThing { get; set; }
}
internal class SomeOutput : ITOutput {
public Guid SomeGuid { get; set; }
}
internal class SomeOtherOutput : ITOutput {
public Guid SomeGuid { get; set; }
}
最后,这里是我们可以一般地处理这些问题的用法:
var manglers = new List<Mangler<ITInput, ITOutput>>();
manglers.Add( new Mangler<ITInput, ITOutput>
{ Input = new SomeInput(), Output = new SomeOutput() } );
manglers.Add( new Mangler<ITInput, ITOutput>
{ Input = new AnotherInput(), Output = new SomeOutput() } );
foreach( var thisMangler in manglers ) {
var input = thisMangler.Input;
var output = thisMangler.Output;
var success = thisMangler.IsInputAGuid();
}
您可以在foreach
中看到,无论具体类型如何,我们都可以在所有类型上调用Input
,Output
和IsInputAGuid()
。
因此,在您的代码中找到哪些代码是通用的,然后将上述技术应用于它。您可以使用接口或基类来约束。