Nick
Nick

Reputation: 705

Adding a generic type constraint halfway through a method

I have two generic methods -

public CustomObject<T> MethodA<T>(T arg1) where T : class
{
    ...
    return MethodB<T>(arg1);
}


public CustomObject<R> MethodB<R>(R arg2) where R : class, IInterface
{
    ...
    return new CustomObject<R>();
}

The problem is clearly that I can't call MethodB with a type that doesn't implement IInterface (which T doesn't). But what if I did this -

public CustomObject<T> MethodA(T arg1) where T : class
{
    ...
    var casted = arg1 as IInterface;
    if (casted != null)
    {
        return MethodB<T>(casted);
    }
}

Obviously this doesn't compile, yet it should, no? How can I let the compiler know that I know that casted implements IInterface and is a class so the call to MethodB is fine? The big wrinkle in here is probably that I'm trying to return CustomObject<T>.

Upvotes: 4

Views: 88

Answers (2)

MineR
MineR

Reputation: 2194

Because your CustomObject<T> is generic, it's problematic. For example, CustomObject<object> is not interchangeable with CustomObject<string>, but you can convert between the two.

You could do this as a workaround:

public class CustomObject<T> where T : class {}
public interface IInterface { }

public static class CustomObjectConverter
{
    public static CustomObject<T1> ConvertTo<T1, T2>(CustomObject<T2> other)
        where T1 : class
        where T2 : class
    {
        return new CustomObject<T1>();
    }
}

public CustomObject<T> MethodA<T>(T arg1) where T : class
{
    if (arg1 is IInterface inf)
    {
        var b = MethodB(inf);
        return CustomObjectConverter.ConvertTo<T,IInterface>(b);
    }
    return null;
}
public CustomObject<T> MethodB<T>(T arg2) where T : class, IInterface
{
    return new CustomObject<T>();
}

Upvotes: -1

Enigmativity
Enigmativity

Reputation: 117047

You need to use reflection to make this work.

Try this:

public CustomObject<T> MethodA<T>(T arg1) where T : class
{
    if (arg1 is IInterface)
    {
        var method = this.GetType().GetMethod("MethodB").MakeGenericMethod(arg1.GetType());
        return (CustomObject<T>)method.Invoke(this, new [] { arg1 });
    }
    return null;
}

Upvotes: 3

Related Questions