Почему c# компилятор испускает Активатор. CreateInstance при назывании новым в с универсальным типом с новым () ограничение?

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

  1. Если под «двоичным кодированным» вы подразумевали двоичное кодирование 5, то да. Дробное кодирование 5 и двоичное кодирование 5 имеют открытый текст x ^ 2 + 1.

  2. Если под «массивом, состоящим из E (1), E (0), E (1)» вы подразумевали 3 шифротекста, которые соответственно расшифровываются до 1, 0 и 1, то нет.

    [113 ]

Извлечение k-го бита (обозначаемого m_k) числа m из его дробного / целочисленного / двоичного кодирования M (x) = m_ {n-1} x ^ {n-1} + ... + m_k x ^ k + ... + m_0 эквивалентно нахождению функции F такой, что для заданного k и любого m F (M (x)) = m_k в \ ZZ_2 [x ] / (х ^ п + 1). Такую функцию нетривиально найти. Даже если он существует, он может иметь форму многочлена 2 ^ n степени, который слишком глубок для гомоморфной оценки.

  1. Если под «массивом, состоящим из E (1), E (0), E (1)», имеется в виду 1 зашифрованный текст, который расшифровывается в вектор [1, 0, 1], то нет. [114 ]

Сначала нужно решить сценарий 2, изложенный выше, и успешно извлечь эти отдельные биты. Все остальное - это просто группировка по шифротекстам, что можно легко сделать с помощью rotate_rows в SEAL.

17
задан Nathan W 15 December 2008 в 06:03
поделиться

5 ответов

Я подозреваю, что это - проблема JITting. В настоящее время JIT снова использует тот же сгенерированный код для всех аргументов ссылочного типа - так a List<string>vtable точки к тому же машинному коду как машинный код List<Stream>. Это не работало бы если каждый new T() звоните должен был быть разрешен в коде JITted.

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

Одна интересная небольшая точка: ни в том, ни в другом случае делает конструктора без параметров типа значения, названы, если существует один (который очень редок). Посмотрите мое недавнее сообщение в блоге для деталей. Я не знаю, существует ли какой-либо способ вызвать его в деревьях выражений.

9
ответ дан 30 November 2019 в 13:22
поделиться

Это вероятно, потому что не ясно, является ли T типом значения или ссылочным типом. Создание этих двух типов в неуниверсальном сценарии производит совсем другой IL. Перед лицом этой неоднозначности C# вынужден использовать универсальный метод создания типа. Активатор. CreateInstance отвечает всем требованиям.

Быстрое экспериментирование, кажется, поддерживает эту идею. Если Вы введете в следующем коде и исследуете IL, то он будет использовать initobj вместо CreateInstance, потому что нет никакой неоднозначности на типе.

static void Create<T>()
    where T : struct
{
    var x = new T();
    Console.WriteLine(x.ToString());
}

Переключение его к классу и новый () ограничение, хотя все еще вызывает Активатор. CreateInstance.

8
ответ дан 30 November 2019 в 13:22
поделиться

Интересное наблюдение :)

Вот более простая вариация на Ваше решение:

static T Create<T>() where T : new()
{
  Expression<Func<T>> e = () => new T();
  return e.Compile()();
}

Очевидно наивный (и возможный медленный) :)

2
ответ дан 30 November 2019 в 13:22
поделиться

Зачем нужен этот обходной путь?

Потому что общее ограничение new () было добавлено в C # 2.0 в .NET 2.0.

Expression и его друзья были добавлены в .NET 3.5.

Итак, ваш обходной путь необходим, потому что это было невозможно в .NET 2.0. Между тем, (1) использование Activator.CreateInstance () было возможно, и (2) в IL отсутствует способ реализации 'new T ()', поэтому Activator.CreateInstance () использовался для реализации этого поведения.

3
ответ дан 30 November 2019 в 13:22
поделиться

Это немного быстрее, поскольку выражение компилируется только один раз:

public class Foo<T> where T : new()
{
    static Expression<Func<T>> x = () => new T();
    static Func<T> f = x.Compile();

    public static T build()
    {
        return f();
    }
}

Анализируя производительность, этот метод работает так же быстро, как и более подробный скомпилированный выражение и намного, намного быстрее, чем new T () (в 160 раз быстрее на моем тестовом ПК).

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

public static Func<T> BuildFn { get { return f; } }
2
ответ дан 30 November 2019 в 13:22
поделиться
Другие вопросы по тегам:

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