tomatoRadar
tomatoRadar

Reputation: 401

C# cast generic type (like C++ user defined conversions)

Is there a way in C# to perform a user defined conversion for generic types ?

for example:

class Stack<T> 
{
    private T x; //should be an array but doesn't matter for this example

    public Stack(T input)
    {
        x = input;
    }

    public Stack<Q> Convert<Q>(Stack<T> inputStack)
    {
        //what would go here ? The call is below.
    }
}

//main code
Stack<int> stack = new Stack<int>(2);
Stack<long> longstack = stack.Convert<long>(stack);

I would imagine that the compiler can deduce that Q is long and T is int in the Convert function, but it doesn't seem to work.

Upvotes: 3

Views: 323

Answers (2)

rtf_leg
rtf_leg

Reputation: 1819

Here is extension method for standart Stack class (you can rewrite it a little and use like instance method in your own Stack class):

public static class MyStackExtensions
{
    public static Stack<TDest> Convert<TSrc, TDest>(
        this Stack<TSrc> stack, 
        Func<TSrc, TDest> converter = null)
    {
        if (stack == null)
            throw new ArgumentNullException("stack");
        var items = converter == null
            ? stack.Select(i => (TDest) System.Convert.ChangeType(i, typeof (TDest)))
            : stack.Select(converter);
        return new Stack<TDest>(items.Reverse());
    }
}

Convert stack from int to long using convert function - no type params needed :-)

var intStack = new Stack<int>(new[] { 1, 2, 3 });
var longStack = intStack.Convert(i => (long)i);

Or using standart conversion:

var intStack = new Stack<int>(new[] { 1, 2, 3 });
var longStack = intStack.Convert<int, long>();

Upvotes: 1

Mat&#237;as Fidemraizer
Mat&#237;as Fidemraizer

Reputation: 64943

No, because class-level generic type parameters can't be auto-infered from usage.

I would imagine that the compiler can deduce that Q is long and T is int in the Convert function, but it doesn't seem to work.

Maybe, but at the end of the day, a generic type parameter doesn't belong to constructor. That is, you provide a generic argument to the type based on what constructor parameter/argument? What happens if there're more than a constructor parameter?

public class A<T>
{
    // Which one should be used to auto-infer T from usage?
    // Maybe the integer? Or the bool? Or just the string...?
    // Every choice seems a joke, because it would be absolutely
    // arbitrary and unpredictable...
    public A(int x, string y, bool z)
    {
    }
}

Now take your sample code as example. It has the same issue: what argument should be used from your Convert static method to infer generic type argument from usage? What happens if Convert has more than an argument...?

Upvotes: 3

Related Questions