0

Consider the following short program:

public interface IFoo<T> {}

public class Foo : IFoo<string> {}

public static class ExtensionFoo
{
    public static TFoo Bar<TFoo, T>(this TFoo foo)
        where TFoo : IFoo<T>
    {
        System.Console.WriteLine($"I never got to know what is {default(T)}");
        return foo;
    }
}

public class Program
{
    public static void Main()
    {
        // Error, types can not be inferred for some reason
        var foo = new Foo().Bar();
        
        // Working, but redundant
        // var foo = new Foo().Bar<Foo,string>();
        
        // Error, as expected
        // var foo = new Foo().Bar<Foo,int>();
    }
}

Why the C# type system does not permit the concise expression: var foo = new Foo().Bar()?

Is there a deep reason why types can not be resolved in such expressions?

Is it possible in general to avoid types to pop up in such fluent compositions?

This was tested on .Net Core 3.1.

  • 4
    why, because it doesn't. I'm not sure what you expect as an answer here? That's just how the compiler has been designed. The implicit resolving of generics was/is just a short hand – Liam Nov 05 '20 at 15:34
  • 1
    I guess, that you'll need an answer from this question [Why doesn't C# infer my generic types?](https://stackoverflow.com/questions/8511066/why-doesnt-c-sharp-infer-my-generic-types) Compiler doesn't infer generic types based on the return type – Pavel Anikhouski Nov 05 '20 at 15:38
  • The problem is that extension methods run in a static context hence the types are not transferred to the extension method so I would say it is not a limitation, it is a feature! – Lucky Brain Nov 05 '20 at 15:43
  • If it isn't a bug (and it isn't) then by definition it must be intentional. – Matthew Watson Nov 05 '20 at 15:44
  • Eric Lippert answers this [here](https://stackoverflow.com/questions/7171067/no-type-inference-with-generic-extension-method) - likely a duplicate question. – Matthew Watson Nov 05 '20 at 15:46
  • Here's the [archived copy of Eric Lippert's blog entry](https://learn.microsoft.com/en-gb/archive/blogs/ericlippert/constraints-are-not-part-of-the-signature) that addresses this issue. (The link from the duplicate question is broken.) – Matthew Watson Nov 05 '20 at 15:54
  • @Servy - You may be correct on some matter, but a language that is used by millions should have no mysteries and every, or atleast almost every, aspect of the language should be known. There should be IMHO not a single design in C#, where everyone on this planet says "I have no idea why it is designed like this ask the person who did it." and that is what OP is trying to figure out why is it designed like this or maybe am I doing something wrong. – Rand Random Nov 05 '20 at 16:06
  • @MatthewWatson - edited the answer of your linked question with your provided URL – Rand Random Nov 05 '20 at 16:09
  • 2
    @RandRandom Your assertion that the language developers ought to publicly explain why they've designed various language features is not relevant to whether a question about why a language was designed the way that it was should be on topic *here*. It's great for language designers to publish their reasoning for design decisions. But if you want to ask a language designer why they choose to do something you need to *ask them*, not asking users here on SO who aren't capable of providing such an answer. – Servy Nov 05 '20 at 16:22
  • @MatthewWatson - thank you for the link to the article. However, what Eric is explaining in the article does not directly relate to my problem. He is discussing how the type system resolves an overloaded function and how the type constraints do not play a role in this process, etc. Apparently the type constrains are not used for type inferrence but only for type validations - unfortunately. – Benjamin Batistic Nov 05 '20 at 16:28
  • *not a single design in C#, where everyone on this planet says "I have no idea why it is designed like this ask the person who did it."* you're going to be disappointed – Liam Nov 05 '20 at 16:49

1 Answers1

4

Why the C# type system does not permit the concise expression: var foo = new Foo().Bar()?

One reason is because T is not necessarily string, as is highlighted through following scenario:

public class Foo : IFoo<string>, IFoo<int> { }

Types must be able to be inferred in 100% of cases, otherwise they need to be made explicit.

Johnathan Barclay
  • 18,599
  • 1
  • 22
  • 35
  • Hm, but this is not how `Foo` is defined. In this case I understand the type is ambiguous. Everything is transparent to the compiler. Or am I missing something? – Benjamin Batistic Nov 05 '20 at 15:49
  • 1
    @JohnathanBarclay Adding an interface is *already* a breaking change *whether or not this feature exists*. Even with the language as it is now, you can construct situations where adding an interface makes previously compiling code error or behave differently (overload resolution being the best example). – Servy Nov 05 '20 at 16:25
  • @Servy Yes you are correct. – Johnathan Barclay Nov 05 '20 at 16:36