Question

I have a method written in terms of types T and K

public K Process<T,K> (IEnumerable<T> set)
{
    //do stuff to set
}

I use LINQ to get some projection of my data and I need to send it for processing

var dataSlice=records.Select(r => new { name = r.GetName(), id = r.GetId() });
string result =  Process <?, string>(dataSlice);

What should I specify for ? (if it can be done)

Was it helpful?

Solution

You can't directly because dataSlice is now a collection of anonymous types, you can try leaving the type information out:

string result = Process(dataSlice);

Sometimes the compiler can infer the correct types for you, it saves typing and can be useful!

If that doesn't work, then you'd probably be better off not using an anonymous type and creating a proper type to hold the data, or use something like a Tuple.

Anonymous types are great, but they're mostly used for shuttling data between linq queries without resorting to custom types.

Although even if you could get past the compiler, your Process method won't know what it's getting and as such won't be able to extract an element from dataSlice, so it's best to go down a custom type route or use a Tuple as stated earlier.

OTHER TIPS

I like this simple tool:

public static class Klass
{
    public static Klass<T> Of<T>(){ return Klass<T>.instance; }
}

public class Klass<T>
{
    public static Klass<T> instance = null;
}

and now you can:

public K Process<T,K>(Klass<T> t, IEnumerable<K> items)
{
    ....
}

var aKey = Process(Klass.Of<string>(), mySetOfItems);
// aKey will be autotyped to a string

but note that this required the addition of an unused parameter to the Process method. This parameter is used solely just to resolve the missing type. This is why the 'instance' is always null. The value is not important, all that counts is that this null is of type Klass.

However, note that this 100%ly saves you from using explicit type parameters like in Process<string, ....> because you do not need to explitely pass the <string> type parameter. So, all type parameters are bound to arguments and this allows the copiler to automatically resolve the anonymous types, including the IEnumerable's item.

Edit: I've just remembered about one more thing, albeit more complicated and tricky. Anonymous types are fully ducktyped. This means that one anonymous type with "string Key, int Value" is absolutely of the same class as a second anonymous type created elsewhere which also is "string Key, int Value". This allows you to create a small helper method described here CastByExample.

Normally, you cannot "specify" the anonymous type, because, well, it is unnamed, and you cannot write the name of it. But, thanks to the ducktyping, this precious article shows how can you provide a never-executed lambda that returns a "sample" anonymous object just for the purpose of intercepting the anonymous-type that it defines, so that type can be passed down the chain of expressions. Very cornercase'y, but interesting thing!

The short answer is that you can't without redesigning your method. C# you must either specify all type parameters or none.

One option is to wrap your Process method in a separate API.

public class Processor<T>
{
    public K Process<K>() { ... }
}

...

public Processor<T> CreateProcessor<T> (IEnumerable<T> set)
{
    return new Processor<T>(set)
}

...

string result =  CreateProcessor(dataSlice).Process<string>();

Here's an alternative, though it's a bit less intuitive, IMO:

public static class Process<K>
{
    public static K From<T>(Ienumerable<T> set) { ... }
}

...

string result = Process<string>.From(dataSlice);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top