То, как я обнаруживаю, что объект является универсальным набором, и что вводит его, содержит?

В C # 7.3 у вас могут быть асинхронные точки входа, я предлагаю использовать это.

Некоторые примечания:

  1. Не используйте асинхронную пустоту, у нее есть тонкости в том, как она работает с ошибками, если вы видите, что вы пишете сам асинхронную пустоту, тогда подумайте, кто вы делает. Если это не для обработчика событий, вы, вероятно, делаете что-то не так
  2. Если вы хотите дождаться завершения ряда задач, используйте Task.WhenAll

Модифицированный пример

static async Task Main(string[] args)
{
   Console.WriteLine("Start Task");
   var task = Program.step1();

   for (int i = 0; i < 6; i++)
   {
      await Task.Delay(100);
      Console.WriteLine("Sleep-Loop");
   }

   Console.WriteLine("waiting for the task to finish");
   await task;
   Console.WriteLine("finished");
   Console.ReadKey();
}

private static async Task step1()
{
   await Task.Delay(1000);
   Console.WriteLine("Step1");
   await Program.step2();
}

private static async Task step2()
{
   await Task.Delay(1000);
   Console.WriteLine("Step2");
}

Важно отметить, что задачи не являются потоками и async не параллельны, однако они могут быть.

9 раз из 10, если вы используете шаблон асинхронного ожидания, работа, связанная с вводом-выводом, должна использовать порты завершения ввода-вывода операционной системы, чтобы вы могли освободить потоки. Это функция масштабируемости и отзывчивости пользовательского интерфейса.

Если вы не выполняете какую-либо работу ввода-вывода, тогда на самом деле совсем нет нужды в паттерне async await, и, как следствие, такая работа процессора, вероятно, должна быть просто заключена в Task.Run в точке вызова. Не упакован в методе async.

На этом этапе также полезно отметить, что использование только задач не является асинхронным и ожидающим шаблоном. Хотя у них обоих есть общие задачи, они не одно и то же.

И последнее; если вы считаете, что вам нужно использовать асинхронный код с огнем и забыть, очень тщательно подумайте, как вы будете обрабатывать любые ошибки.

Вот несколько рекомендаций.

  • Если вы хотите выполнить работу ввода-вывода, используйте шаблон асинхронного ожидания.
  • Если вы хотите выполнить работу процессора, используйте Task.Run.
  • Никогда не используйте async void, кроме как для обработчика событий.
  • Никогда не переносите работу ЦП в асинхронном методе, пусть вызывающая сторона использует Task.Run
  • Если вам нужно дождаться выполнения задачи, await ее, никогда не вызывайте Result или [ 1110] или используйте Task.WhenAll
10
задан Community 23 May 2017 в 10:27
поделиться

3 ответа

Re ваша головоломка; Я предполагаю stringifyList является универсальным методом? Вам нужно вызвать его с помощью отражения:

MethodInfo method = typeof(SomeType).GetMethod("stringifyList")
            .MakeGenericMethod(lt).Invoke({target}, new object[] {o});

, где {target} равно null для статического метода, или this для метода экземпляра на текущем экземпляр.

Далее - я бы не предположил, что все коллекции являются: основанными на List , b: универсальными типами. Важно то, что они реализуют IList для некоторого T ?

Вот полный пример:

using System;
using System.Collections.Generic;
static class Program {
    static Type GetListType(Type type) {
        foreach (Type intType in type.GetInterfaces()) {
            if (intType.IsGenericType
                && intType.GetGenericTypeDefinition() == typeof(IList<>)) {
                return intType.GetGenericArguments()[0];
            }
        }
        return null;
    }
    static void Main() {
        object o = new List<int> { 1, 2, 3, 4, 5 };
        Type t = o.GetType();
        Type lt = GetListType(t);
        if (lt != null) {
            typeof(Program).GetMethod("StringifyList")
                .MakeGenericMethod(lt).Invoke(null,
                new object[] { o });
        }
    }
    public static void StringifyList<T>(IList<T> list) {
        Console.WriteLine("Working with " + typeof(T).Name);
    }
}
6
ответ дан 3 December 2019 в 23:15
поделиться

Используйте Type для сбора необходимой информации.

Для универсальных объектов вызовите GetType (), чтобы получить их тип и затем проверьте IsGenericType , чтобы узнать, является ли он универсальным вообще. Если это так, вы можете получить определение универсального типа, которое можно сравнить, например, так: typeof (List <>) == yourType.GetGenericTypeDefinition () . Чтобы выяснить, что такое универсальные типы, используйте метод GetGenericArguments , который будет возвращать массив используемых типов.

Для сравнения типов вы можете сделать следующее: if (typeof ( int) .IsAssignableFrom (yourGenericTypeArgument)) .


РЕДАКТИРОВАТЬ, чтобы ответить на продолжение:

Просто заставьте ваш метод stringifyList принять IEnumerable (не универсальный) в качестве параметра и может быть, также известный аргумент обобщенного типа, и вы будете в порядке; затем вы можете использовать foreach , чтобы просмотреть все элементы и обработать их в зависимости от аргумента типа, если это необходимо.

7
ответ дан 3 December 2019 в 23:15
поделиться

На самом базовом уровне все универсальные списки реализуют IEnumerable , который находится в сам потомок IEnumerable . Если вы хотите сериализовать список, то вы можете просто привести его к IEnumerable и перечислить общие объекты внутри него.

Причина, по которой вы не можете сделать

Type lt = t.GetGenericArguments()[0];
List<lt> x = (List<lt>)o;
stringifyList(x);

, заключается в том, что обобщенные типы все еще должны быть статически строго типизированы, и что вы пытаетесь сделать, это создать динамический тип. List и List , несмотря на использование одного и того же универсального интерфейса, представляют собой два совершенно разных типа, и вы не можете привести их между собой.

List<int> intList = new List<int>();
List<string> strList = intList; // error!

Какой тип получит stringifyList (x) ? Самый базовый интерфейс, который вы можете здесь передать, это IEnumerable , так как IList не наследуется от IList .

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

1
ответ дан 3 December 2019 в 23:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: