0

Imagine that you want to declare an object with an anonymous type, but you need it to be generic (I can't think of an actual reason why, this is theoretical). How would you create such an object?

For example:

var anonymousGeneric = new <T>{ }; // <- doesn't work

var anonymousGeneric = Activator.CreateInstance((new { }).GetType()); // Not generic 

edit:

// because:
(new { }).GetType().IsGenericType == false
// Of course, any useful anonymous object _will_ be generic:
(new { a="b" }).GetType().IsGenericType == true
// But in the process of testing various aspects of this question 
// it had never occurred to me that I needed to supply any property 
// (this was all theoretical, remember)

end edit

But neither of those works. Of course, the real-world solution to this imagined problem is to define an actual class definition:

public GenericThing<T> { }

But that isn't anonymous like above.

Once the object is created, imagine using it later on with something like:

var anonymousGenericType = anonymousGeneric.GetType();

// These throw exception
// <>f__AnonymousType0#1 is not a GenericTypeDefinition. MakeGenericType may only be called on a type for which  Type.IsGenericTypeDefinition is true.
//   + System.RuntimeType.MakeGenericType(System.Type[])
var intThing = anonymousGenericType.MakeGenericType(typeof(int));
var stringThing = anonymousGenericType.MakeGenericType(typeof(string));  

In summary, is it possible to create an anonymous generic object?

BurnsBA
  • 4,347
  • 27
  • 39
  • 1
    Anonymous objects are already created with something that behaves like type parameters: `new { Blargh = "foo" };` `Blargh` is a string. If you created `new { Blargh = 9 }`, that'd be an integer. What changes when you stick a `` on it? Remember, anonymous types were added as a replacement for generic `Tuple` – 15ee8f99-57ff-4f92-890c-b56153 Oct 20 '17 at 19:59
  • dont you think anonymous is already generic by definition? and if it has type, defined statically or through generics, then its not anonymous? – dee zg Oct 20 '17 at 20:00
  • 2
    @deezg An anonymous type *does* have a type (by definition on fact), and it's in fact a type that's defined statically, it's just a type that doesn't have a name (or at least not one that you can use). – Servy Oct 20 '17 at 20:02
  • [Why Are Anonymous Types Generic?](https://blogs.msdn.microsoft.com/ericlippert/2010/12/20/why-are-anonymous-types-generic/) *It's coming from inside the house!!* Did you try `var anonymousGenericType = anonymousGeneric.GetType().GetGenericTypeDefinition();` – 15ee8f99-57ff-4f92-890c-b56153 Oct 20 '17 at 20:05
  • @EdPlunkett While true, it's just an implementation detail, and doesn't seem like it would help the OP do...whatever the heck it is that they're actually trying to do, which they should really properly explain. Specifically, the fact that the implementation of an anonymous type uses generics still doesn't ever result in you having access to an open generic type, which the OP appears to want. – Servy Oct 20 '17 at 20:08
  • I don't think the OP is trying to accomplish anything in particular beyond exploring the limits and capabilities of the language. –  Oct 20 '17 at 20:09
  • 6
    Anonymous types are already implemented as generic types. What problem are you actually trying to solve here? – Eric Lippert Oct 20 '17 at 20:12
  • @ericlippert call `MakeGenericType` from an anonymous object (for no real reason). I suspect the answer is "this isn't possible without mucking with IL" but perhaps I'm just not aware of some method call/parameter – BurnsBA Oct 20 '17 at 20:24
  • @EricLippert part of my confusion stems from `(new { }).GetType().GetGenericTypeDefinition().IsGenericType` throwing a run time exception because it is not generic. Of course you are correct that any usable type with a property is generic. – BurnsBA Oct 20 '17 at 21:14
  • So, you want an empty anonymous type to be genericized in some number of type parameters... why? There are almost certainly better ways to do what you want. – Eric Lippert Oct 20 '17 at 21:17
  • Yes, as mentioned previously, this is mostly just a thought experiment from learning about C# reflection with the Visual Studio interactive shell. – BurnsBA Oct 20 '17 at 21:38
  • @Servy are you talking about anonymous instance or type? – dee zg Oct 21 '17 at 04:04

2 Answers2

3

(I can't think of an actual reason why, this is theoretical)

In that case, let's stick with the simple and obvious, since it's easier to find a reason: simply create a regular anonymous object from a generic method.

public object Foo<T>(T t) { return new { t }; }

Here, Foo(0) and Foo("") will necessarily return different types, but they'll still share a type definition.

Pretty much any use of anonymous types can make equal sense inside a generic method.

  • Curious - > but they'll still share a type definition. Does this serve any purpose? – ryanwebjackson Oct 20 '17 at 20:33
  • 2
    @ryanwebjackson For the programmer, not really. For the compiler, it would be hard to implement differently. –  Oct 20 '17 at 21:01
1

anonymousGeneric.GetType() is returning the wrong type of generic type: Closed (with type parameter(s)) vs open (without)1. If you want to change a type parameter, you need to get the generic type definition from it.

The following actually works, though I can't imagine what good it does anybody 2:

var anonymousGeneric = new {a = "b"};

var anonymousGenericType = anonymousGeneric.GetType().GetGenericTypeDefinition();

var intThingType = anonymousGenericType.MakeGenericType(typeof(int));

var intThingInstance = Activator.CreateInstance(intThingType, 9);

Now we have a thing just like anonymousGeneric, but its type parameter is int instead of string, and its a property is 9. But what's it good for? How do you declare a reference to it? You could bind to its properties in XAML, if you had some time on your hands.


1 Thanks to Amy and Servy for pitching in to clear up my confusion with terminology.

2 Note that there are more things in heaven and earth than are dreamt of in my philosophy.

  • 2
    `List` is a *closed-* generic type. `List` is an *open-* generic type. They are both generics. –  Oct 20 '17 at 20:12
  • @Amy Thanks for the clarification. I wasn't familiar with those terms. Still aren't, but now I know what to google. – 15ee8f99-57ff-4f92-890c-b56153 Oct 20 '17 at 20:15
  • 1
    *[asks Amy for details]* – Robert Harvey Oct 20 '17 at 20:15
  • 3
    I love the juxtaposition of these sentences: "Ask amy for details. It actually works, but i can't imagine what good it does anybody." –  Oct 20 '17 at 20:16
  • @RobertHarvey https://stackoverflow.com/questions/1735035/generics-open-and-closed-constructed-types – Servy Oct 20 '17 at 20:16
  • @Servy: *[shrug]* I was joking (rather unsuccessfully, apparently). – Robert Harvey Oct 20 '17 at 20:17
  • 2
    *gives @RobertHarvey **all** the details* –  Oct 20 '17 at 20:19
  • Mmmm... Details. – Robert Harvey Oct 20 '17 at 20:19
  • 1
    `...though I can't imagine what good it does anybody` -- The [MSDN documentation](https://msdn.microsoft.com/en-us/library/system.type.makegenerictype(v=vs.110).aspx) states that *"Types constructed with MakeGenericType can be open; that is, some of their type arguments can be type parameters of enclosing generic methods or types. You might use such open constructed types when you emit dynamic assemblies."* – Robert Harvey Oct 20 '17 at 20:22
  • 1
    So, this question I asked could have been avoided if I had noticed the difference. If you do not provide a property then anonymous type is not generic: `(new { }).GetType().GetGenericTypeDefinition().IsGenericType` -> runtime exception. Of course, your solution here works. thanks. – BurnsBA Oct 20 '17 at 21:13
  • @BurnsBA You know what, it didn’t even cross my mind that the lack of properties in your `{}` was the point. Oh well. – 15ee8f99-57ff-4f92-890c-b56153 Oct 20 '17 at 21:16