确定一个类型是否为匿名类型

26
在 C# 3.0 中,是否有可能确定一个 Type 实例表示的是匿名类型?

另请参见答案:https://dev59.com/MXRC5IYBdhLWcg3wYP-h#315186 - Brian Low
6个回答

40

尽管匿名类型是普通类型,但您可以使用一些启发式方法:

public static class TypeExtension {

    public static Boolean IsAnonymousType(this Type type) {
        Boolean hasCompilerGeneratedAttribute = type.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Count() > 0;
        Boolean nameContainsAnonymousType = type.FullName.Contains("AnonymousType");
        Boolean isAnonymousType = hasCompilerGeneratedAttribute && nameContainsAnonymousType;

        return isAnonymousType;
    }
}

另一个好的启发式方法是,如果类名是有效的 C# 名称(匿名类型生成的名称不符合有效的 C# 类名 - 使用正则表达式来处理)。


@Philip 但并非万无一失,请参考这个问题。 - Matt Warren
1
@MattWarren,是哪个问题? - Gennady Vanin Геннадий Ванин
2
在 Mono 上,type.FullName.Contains("AnonymousType") 不成立。 - albertjan
请注意 - 如果您在泛型类或函数内部检查类型,则此方法无效。 - Thomas Johnson
澄清:如果您正在检查泛型类/方法中的类型参数,则此方法无效。请检查对象实例的.GetType()结果。 - Thomas Johnson

20

匿名类型对象的属性

  • 命名空间等于 null
  • 基础类型为 System.Object
  • IsSealed = true
  • 自定义特性 0 为 DebuggerDisplayAttribute,类型:""
  • IsPublic = false

对于我的特定应用程序而言,如果命名空间为 null,则可以推断该类型为匿名类型,因此检查命名空间是否为 null 可能是最便宜的检查。


2
谢谢,选择返回类型.NameSpace == null; 将我的程序处理速度提高了近50%(之前使用的是这种方法:https://dev59.com/i3E95IYBdhLWcg3wDpcG) - Schalk
是的,这应该是正确答案。我不认为任何合理的具体类会有一个空的命名空间。 - Christopher Davies
+1 谢谢!我在这里留下我的评论,以便将此答案收藏(不仅是帖子)。 - Gennady Vanin Геннадий Ванин
我认为全局类可以具有命名空间== null; 所以仅进行该检查是不够的。@Schalk - nawfal
@user2864740 C#确实有空名称空间类的概念。尝试在其周围使用没有名称空间的类。 - nawfal
显示剩余2条评论

6

在C#语言中没有一种构造可以让你说“这是一个匿名类型”。你可以使用简单的启发式方法来近似判断一个类型是否为匿名类型,但是可能会被手动编写IL代码的人或使用某些字符(如>和<)作为标识符的语言所欺骗。

public static class TypeExtensions {
  public static bool IsAnonymousType(this Type t) {
    var name = t.Name;
    if ( name.Length < 3 ) {
      return false;
    }
    return name[0] == '<' 
        && name[1] == '>' 
        && name.IndexOf("AnonymousType", StringComparison.Ordinal) > 0;
}

2
在元数据和CLR中,没有匿名类型这样的术语。匿名类型仅是编译器功能。

1

可能知道你为什么想知道这个。如果你执行以下操作:

var myType = new { Name = "Bill" };
Console.Write( myType.GetType().Name  );

...你会看到类名输出为"<>f__AnonymousType0`1"。根据你的需求,你可以假设以"<>"开头,包含"AnonymousType"和反引号字符的类型就是你要找的。


不用担心为什么。这只是好奇心 :) - xyz
我也曾这么想过,但这有点不太保险。如果在c#5中更改了名称会怎么样?任何使用该名称的代码都将失效。 - Philip Wallace
重要的是要问和解释“为什么”,因为通常有其他可能的答案,如果不了解更多信息,这些答案可能不明显。 - Samuel Neff

1

匿名类型似乎会被添加一个DebuggerDisplayAttribute,其中Type = "<Anonymous Type>"

编辑:但只有在调试模式下编译时才会添加。糟糕。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接