Anonymous Types - Are There Any Distingushing Characteristics

Anonymous Types - Are there any distingushing characteristics?

EDIT: The list below applies to C# anonymous types. VB.NET has different rules - in particular, it can generate mutable anonymous types (and does by default). Jared has pointed out in the comment that the naming style is different, too. Basically this is all pretty fragile...

You can't identify it in a generic constraint, but:

  • It will be a class (rather than interface, enum, struct etc)
  • It will have the CompilerGeneratedAttribute applied to it
  • It will override Equals, GetHashCode and ToString
  • It will be in the global namespace
  • It will not be nested in another type
  • It will be internal
  • It will be sealed
  • It will derive directly from object
  • It will be generic with as many type parameters as properties. (You can have a non-generic anonymous type, with no properties. It's a bit pointless though.)
  • Each property will have a type parameter with a name including the property name, and will be of that type parameter, e.g. the Name property becomes a property of type <>_Name
  • Each property will be public and read-only
  • For each property there will be a corresponding readonly private field
  • There will be no other properties or fields
  • There will be a constructor taking one parameter corresponding to each type parameter, in the same order as the type parameters
  • Each method and property will have the DebuggerHiddenAttribute applied to it.
  • The name of the type will start with "<>" and contain "AnonymousType"

Very little of this is guaranteed by the specification, however - so it could all change in the next version of the compiler, or if you use Mono etc.

Determining whether a Type is an Anonymous Type

Even though an anonymous type is an ordinary type, you can use some heuristics:

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;
}
}

Another good heuristic to be used is if the class name is a valid C# name (anonymous type are generated with no valid C# class names - use regular expression for this).

Get read/write properties of Anonymous Type

Anonymous types generated from C# are always immutable, so the set of writable properties is empty. In VB it's optional: each property defaults to being mutable, but if you prefix it with Key it's immutable; only properties declared using Key count for equality and hash code generation. Personally I prefer C#'s approach.

CanWrite isn't always returned as true for properties in non-anonymous types - only for writable ones. Properties can be read-only, write-only, or read-write. For example:

public class Test
{
// CanWrite will return false. CanRead will return true.
public int ReadOnly { get { return 10; } }

// CanWrite will return true. CanRead will return false.
public int WriteOnly { set {} }

// CanWrite will return true. CanRead will return true.
public int ReadWrite { get { return 10; } set {} }
}

How To Test if a Type is Anonymous?

From http://www.liensberger.it/web/blog/?p=191:

private static bool CheckIfAnonymousType(Type type)
{
if (type == null)
throw new ArgumentNullException("type");

// HACK: The only way to detect anonymous types right now.
return Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute), false)
&& type.IsGenericType && type.Name.Contains("AnonymousType")
&& (type.Name.StartsWith("<>") || type.Name.StartsWith("VB$"))
&& type.Attributes.HasFlag(TypeAttributes.NotPublic);
}

EDIT:

Another link with extension method: Determining whether a Type is an Anonymous Type

How To Test if a Type is Anonymous?

From http://www.liensberger.it/web/blog/?p=191:

private static bool CheckIfAnonymousType(Type type)
{
if (type == null)
throw new ArgumentNullException("type");

// HACK: The only way to detect anonymous types right now.
return Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute), false)
&& type.IsGenericType && type.Name.Contains("AnonymousType")
&& (type.Name.StartsWith("<>") || type.Name.StartsWith("VB$"))
&& type.Attributes.HasFlag(TypeAttributes.NotPublic);
}

EDIT:

Another link with extension method: Determining whether a Type is an Anonymous Type

Non-read only alternative to anonymous types

No, you'll have to create your own class or struct to do this (preferrably a class if you want it to be mutable - mutable structs are horrible).

If you don't care about Equals/ToString/GetHashCode implementations, that's pretty easy:

public class MyClass {
public bool Foo { get; set; }
public bool Bar { get; set; }
}

(I'd still use properties rather than fields, for various reasons.)

Personally I usually find myself wanting an immutable type which I can pass between methods etc - I want a named version of the existing anonymous type feature...

Is there any way to restrict a generic type parameter to an anonymous type?

No, there are no such constraints in C#. You could add an execution-time check to validate that the type has the characteristics of an anonymous type though.



Related Topics



Leave a reply



Submit