Параметр проверки метода Generi c во время выполнения - PullRequest
0 голосов
/ 12 марта 2020
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 никак не связаны друг с другом.

Ответы [ 3 ]

2 голосов
/ 12 марта 2020

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

Одним из решений является просто написать метод (при условии, что два a не относятся к одному и тому же типу):

private static void MyForEachLoop<T>(IEnumerable<T> enumerable) {
    foreach (var a in enumerable) {
        // long process
    }
}

Или, если a имеют одинаковый тип, это не нужно генерировать c:

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);
}
1 голос
/ 12 марта 2020

Вы можете использовать тип Dynami c.

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
 }
}

Вы можете сделать это более Generi c.

switch (expected.GetType())
{
  case "TestA":
  //do something
  break;

  case "TestA":
  //do something
  break;

  default:
  throw new Exception("unexcepted Type!");
 }

Если вы уверены, Что касается типов, вы можете создать интерфейс, который реализует Список значений, затем передать Интерфейс в качестве аргумента, но это не является чем-то общим c, каждый раз, когда вы должны изменить реализацию вашего класса, и вы должны быть уверены, что у вас есть те же свойства.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...