Учитывая, что нет общего типа, который 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
}
}