Есть ли переключатель компилятора для отключения поддержки Generics в C #? - PullRequest
4 голосов
/ 08 марта 2011

Я работаю с партнером, который пытается переместить сложный драйвер с платформы .NET на .NET MicroFramework.

Проблема в том, что .NET MF не поддерживает Generics, и когда мы пытаемся создать приложение, завершается последняя операция «link» с кодом ошибки «CLR_E_PARSER_UNSUPPORTED_GENERICS». Однако нет информации о ГДЕ (модуль, строка кода).

Насколько нам известно, никто специально не вставлял Generics, и они действительно просматривали код, чтобы определить, в чем проблема, без удачи.

Итак, мой вопрос: есть ли какой-нибудь способ отключить поддержку Generics в VS2010, чтобы компилятор пометил ошибочную строку?

Ответы [ 2 ]

18 голосов
/ 08 марта 2011

Есть ли какой-нибудь способ отключить поддержку Generics в VS2010, чтобы компилятор пометил ошибочную строку?

Да, но это «ядерный» вариант:

using System.Collections.Generic;
class Test
{
    static void Main()
    {
        IEnumerable<int> x = null;
    }
}

C:\> csc /langversion:ISO-1 \foo.cs
Microsoft (R) Visual C# 2010 Compiler version 4.0.30319.1
Copyright (C) Microsoft Corporation. All rights reserved.

c:\foo.cs(9,12): error CS1644: Feature 'generics' cannot be used because it is
        not part of the ISO-1 C# language specification

Переключатель ISO-1 отключает все функции, которых не было в C # 1.0 , которые могут иметь больше функций, чем вы хотите отключить.

Обратите внимание, что этот переключатель не предназначен для переключения "эмулировать C # 1.0 в компиляторе C # 2.0"; если вы хотите запустить компилятор C # 1.0, просто запустите его. Переключатель предназначен для идентификации функций, которых не было в конкретной версии, и запрещения их.

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

6 голосов
/ 08 марта 2011

Нет такого специфического переключателя компилятора.

Вы можете взглянуть на исходный код (или декомпилированный исходный код) и найти использование обобщений. Обобщения могут быть объявлены в вашем проекте или общие конструкции (классы, методы, переменные, ...) могут быть использованы вашим проектом.

Возможно, вы захотите использовать отражение для поиска общих объявлений (классов, методов, полей, ..., но не переменных) в вашей сборке. Чтобы посмотреть на использование дженериков, вам также необходимо ознакомиться с инструкциями по IL. Библиотека вроде Mono.Cecil может помочь вам в этом.

UPDATE

Оказывается (конечно, с помощью Эрика Липперта) вы можете скомпилировать свой код для спецификации C # 1.0 с помощью этого переключателя:

/ langversion: ISO-1

Помимо дженериков, вы также пропустите несколько вещей, которые были добавлены в C # 2.0 и более поздние версии.

КОД ОБРАЗЦА

С Mono.Cecil вы можете загрузить сборку и получить все ее типы:

using Mono.Cecil;
using Mono.Cecil.Rocks;

...

var asm = AssemblyDefinition.ReadAssembly("MyAssembly.dll");
var types = asm.MainModule.GetAllTypes();

А затем начните делать интересные запросы к ним:

var genericTypes = types.Where(type => type.HasGenericParameters);

var genericMethods = types.
  Select(type => 
    type.Methods.Where(method => method.HasGenericParameters));

var genericFields = types.
  Select(type => 
    type.Fields.Where(field => field.DeclaringType.HasGenericParameters));

var genericMethodInstructions = types.Select(type =>
  type.Methods.Where(method => method.HasBody).
  Select(method => method.Body.Instructions.
    Where(instruction => instruction.Operand is MethodReference).
    Select(instruction => (MethodReference)instruction.Operand).
    Where(methodRef => methodRef.Resolve().HasGenericParameters)));
...