【问题标题】:Is there a compiler switch to turn off support for Generics in C#?是否有编译器开关可以关闭对 C# 中泛型的支持?
【发布时间】:2011-03-08 18:44:51
【问题描述】:

我正在与一个合作伙伴合作,我们正在尝试将复杂的驱动程序从 .NET 平台迁移到 .NET MicroFramework。

问题是 .NET MF 不支持泛型,当我们尝试构建应用程序时,最后一个“链接”操作退出,错误代码为“CLR_E_PARSER_UNSUPPORTED_GENERICS”。 但是没有关于 WHERE(模块、代码行)的信息。

据我们所知,没有人故意插入泛型,他们一直在仔细检查代码以确定问题所在,但没有运气。

所以我的问题是:有没有办法在 VS2010 中关闭对泛型的支持,以便编译器标记有问题的行?

【问题讨论】:

  • 可以用反射器反编译。可能是某些语言构造隐式使用泛型,例如匿名类型。见:blogs.msdn.com/b/ericlippert/archive/2010/12/20/…
  • 这是一个非常幼稚的基本建议(如果很明显,请原谅我):为什么不用grep 你的源代码中没有空格的小于号? AFAIK 小于号仅用于小于比较和指定泛型类型时;没有其他的。而且 AFAIK 没有在某处提及完整(封闭)类型名称的情况下实际使用泛型。也许你会发现这样使用泛型......
  • 另外,虽然这很可能对您没有帮助,但我记得当我使用 COM 互操作时,我通常不得不更改 CLSCompliantComVisible 属性值,因为编译器是抱怨使用泛型(COM 无法处理泛型)。也许你也可以为了你的目的滥用这些标志属性(尽管老实说我不这么认为)。
  • @stakx:cmets 中的小于号呢?字符串? XML 文档 cmets? 类型的字段。该程序使用泛型,但没有任何泛型语法。
  • @Eric:1. 是的,毫无疑问,除了感兴趣的匹配项之外,您得到很多错误匹配项。尽管如此:它仍然会将您必须阅读的代码总行数减少到一小部分;其次,这只是一个建议;精通正则表达式的人可能会想出一个排除更多“误报”的模式。 2. "其中 C.X 是 IEnumerable" 类型的字段;没关系,因为 C.X 在某处被声明或初始化,需要找到这些点来捕获泛型类型。但完整的源代码必须搜索。

标签: c# .net generics .net-micro-framework


【解决方案1】:

有没有办法在 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# 2.0 编译器中模拟 C# 1.0”开关;如果您想运行 C# 1.0 编译器,只需运行它。该开关旨在识别特定版本中不存在的功能并禁止它们。

请注意,开关也可能无法完成您需要它做的所有事情。它所做的只是禁止使用通用语法。如果您使用的是泛型 type 而没有实际使用泛型 syntax,则开关不会捕获它。

【讨论】:

  • 非常感谢。我会将这个信息传达给我的合作伙伴,然后返回结果 - 但这看起来很有希望!
  • 更新:不是 C# 代码“隐藏”了任何泛型,而是 Eazfuscator.NET 混淆器在混淆过程中添加了 System.Collections.Generic.Dictionary .
【解决方案2】:

没有这样的特定编译器开关。

您可以查看源代码(或反编译的源代码)并搜索泛型的用法。泛型可以在您的项目中声明,也可以由您的项目使用泛型构造(类、方法、变量等)。

您可能希望使用反射在程序集中查找泛型声明(类、方法、字段,...,但不是变量)。要查找泛型的用法,您还需要查看 IL 指令。像 Mono.Cecil 这样的库可以帮助您解决这个问题。

更新

事实证明(当然,在 Eric Lippert 的帮助下)您可以使用此开关为 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)));

【讨论】:

  • 肯定有这样的编译器开关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-12-30
  • 1970-01-01
  • 2016-09-17
  • 1970-01-01
  • 1970-01-01
  • 2014-12-05
  • 1970-01-01
相关资源
最近更新 更多