rudimenter
rudimenter

Reputation: 3440

Why does the following code not compile?

I can't understand why the following code doesn't compile:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1 {
    public interface ITestCondition<T> {
    }

    public class TestConditionBase<T>: ITestCondition<T> {
    }

    public class TestCondition<T>: TestConditionBase<T> {
    }

    public static class TestConditionExtension {
        public static V Foo<V, T>(this V condition) where V: ITestCondition<T> {
            return condition;
        }
    }

    class Program {
        static void Main(string[] args) {
            new TestCondition<int>().Foo();
        }
    }
}

It says it can't find "foo". But it works perfectly without the generic type.

Upvotes: 1

Views: 351

Answers (3)

Eric Lippert
Eric Lippert

Reputation: 659956

V can be inferred but T cannot, and therefore the call to Foo must fail.

Why can T not be inferred?

When performing method type inference C# never makes a type inference from a constraint. Inferences are made by examining the relationship between arguments and their corresponding formal parameter type. Only after inference is complete do we check to see that the constraint is satisfied.

Upvotes: 4

IdeaHat
IdeaHat

Reputation: 7881

I think you are looking for this as your extension method:

public static class TestConditionExtension
{
    public static ITestCondition<T> Foo<T>(this ITestCondition<T> condition)
    {
        return condition;
    }
}

Since V is always an ITestCondition, there is really no reason to make it more generic than that.

A quick rule of thumb I use when I consider using a generic argument is "Does it matter what type it is". In this case, the specific type J doesn't matter, just the parent type does. So don't use a generic, just use the parent type. Hope that makes sense.

Upvotes: 3

ken2k
ken2k

Reputation: 48975

The compiler doesn't manage to infer the types. Specify them explicitly:

new TestCondition<int>().Foo<TestCondition<int>, int>();

Upvotes: 5

Related Questions