[英]Generic method check parameter in runtime
public override void Test<T> T input)
{
if(input is TypeA)
{
var expected =input as TypeA;
foreach(var a in expected.Values)
{
// long process
}
}
else
{
var expected =input as TypeB;
foreach(var a in expected.Values)
{
//long process
}
}
我如何声明
expected
以便我不必两次编写 foreach 语句? TypeA 和 TypeB 没有任何关系。
鉴于没有TypeA
和TypeB
实现的通用类型,您可以这样做:
public void Test<T>(T input)
{
var expectedA = input as TypeA;
if (expectedA != null)
{
Process(expectedA.Values);
}
var expectedB = input as TypeB;
if (expectedB != null)
{
Process(expectedB.Values);
}
}
private void Process(IEnumerable<Something> values)
{
// long process
}
或者使用模式匹配:
public void Test<T>(T input)
{
if (input is TypeA expectedA)
{
Process(expectedA.Values);
}
if (input is TypeB expectedB)
{
Process(expectedB.Values);
}
}
但是如果我们不检查类型会更好。 这意味着input
几乎可以是任何东西,也许不是TypeA
或TypeB
。 方法最好只关心参数的声明类型。 因此,如果您创建了这样的界面:
public interface IHasWhateverTheseValuesAre
{
IEnumerable<Something> Values { get; set; }
}
TypeA
和TypeB
都可以实现它。 然后你的方法看起来像这样:
public void Test<T>(T input) where T : IHasWhateverTheseValuesAre
{
foreach (var value in input.Values)
{
// whatever
}
}
该方法不关心输入是TypeA
、 TypeB
还是任何其他类型,因此不需要检查。 它只会在您传递实现IHasWhateverTheseValuesAre
东西时编译,因此参数将始终具有该Values
属性。
你提到
这些类型是通过 XSD 创建的,并且在反序列化时以任何方式关联它们都会产生问题。
那应该没关系。 如果你有一个TypeA
或TypeB
的对象,这意味着它已经被反序列化了。 让这两个类实现一个公共接口(根本不会改变它们)不会影响到这一点。
另一种看待它的方式:
如果此方法对一组值进行操作,它是否应该将TypeA
或TypeB
作为参数?
也许它应该看起来像这样:
public void Test(IEnumerable<Something> values)
{
foreach (var value in values)
{
// whatever
}
}
您可以使用类型dynamic 。
public override void Test(object input)
{
dynamic expected = input;
if(input is TypeA)
{
foreach(var a in (expected as TypeA).Values)
{
// long process
}
}
else
{
foreach(var a in (expected as TypeB).Values)
{
//long process
}
}
你可以让它更通用。
switch (expected.GetType())
{
case "TestA":
//do something
break;
case "TestA":
//do something
break;
default:
throw new Exception("unexcepted Type!");
}
如果您确定类型,您可以创建一个实现值列表的接口,然后将该接口作为参数传递,但它不是通用的,每次您应该更改类的实现时,您必须确保具有相同的属性。
希望能帮助到你!
一种解决方案是只编写一个方法(假设两个a
不是同一类型):
private static void MyForEachLoop<T>(IEnumerable<T> enumerable) {
foreach (var a in enumerable) {
// long process
}
}
或者,如果a
s 属于相同类型,则不需要泛型:
private static void MyForEachLoop(IEnumerable<CommonTypeOfTheAs> enumerable) {
foreach (var a in enumerable) {
// long process
}
}
像这样调用它:
if(input is TypeA)
{
var expected = input as TypeA;
MyForEachLoop(expected.Values);
}
else
{
var expected = input as TypeB;
MyForEachLoop(expected.Values);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.