Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[C# feature] Infer generic type arguments in collection initializers #1470

Closed
dsaf opened this issue Mar 22, 2015 · 13 comments
Closed

[C# feature] Infer generic type arguments in collection initializers #1470

dsaf opened this issue Mar 22, 2015 · 13 comments

Comments

@dsaf
Copy link

dsaf commented Mar 22, 2015

This code will currently not work:

public class Sample
{
    public static void Main()
    {
        //Simple Case.
        var list = new List {"A", "B", "C"}; //Zero ambiguity, simple to infer.

        //Advanced Case - best generic type argument inference.
        var animalsList = new List { new Dog(), new Cat() };
    }
}

public abstract class Animal {}

public class Dog : Animal {}

public class Cat : Animal {}

Even the simple case is a big improvement that could be easily achieved (I guess).

PS: should work for Dictionary<,> as well.

@dsaf dsaf changed the title [C# feature] Stronger inference in generic collection initializers. [C# feature] Stronger inference in generic collection initializers Mar 22, 2015
@dsaf dsaf changed the title [C# feature] Stronger inference in generic collection initializers [C# feature] Support inferring type parameters of generic types in collection initializers Mar 22, 2015
@marhoily
Copy link

I'm afraid there will be no consensus as to what common denominator type should be in this case:

class Animal {}
interface ICute {}
interface IExpensive {}

class Dog : Animal, ICute, IExpensive {}
class Cat : Animal, ICute, IExpensive {}
class Dress : ICute, IExpensive {}

new List { new Dog(), new Cat(), new Dress() };

Is it object or ICute, or IExpensive?

@dsaf
Copy link
Author

dsaf commented Mar 23, 2015

I believe it can be inferred from the usage of that list. It's a local value after all.

@GeirGrusom
Copy link

I would have inferred it as object since that is the only type that fits all the arguments. I don't think it should ever infer interfaces at all unless all arguments are explicitly of that interface. In the case of explicit different interfaces there should be a compilation error since it doesn't infer interfaces.

@dsaf
Copy link
Author

dsaf commented Mar 23, 2015

@GeirGrusom - that would certainly be preferable to some complex rules or no type parameter inference at all.

Frankly speaking in most cases all I want is this:

var list = new List {"A", "B", "C"}; //Zero ambiguity, simple to infer.

@aluanhaddad
Copy link

@dsaf I think it would be welcome for simple cases like the example of

var list = new List {"A", "B", "C"};

as this matches the existing semantics of implicitly typed array declarations which are a nice feature.

var array = new [] {"A", "B", "C"};

However, as @marhoily comments, there is often not always an obvious common ancestor.

However, this could be addressed if the language supported intersection types.
In that case,
for

class Animal {}
interface ICute {}
interface IExpensive {}

class Dog : Animal, ICute, IExpensive {}
class Cat : Animal, ICute, IExpensive {}
class Dress : ICute, IExpensive {}

new List { new Dog(), new Cat(), new Dress() };

The inferred type might sensibly be something like

List<ICute with IExpensive>

For example Scala will produce exactly such a synthesized type.

However it can be taken a bit too far in my opinion.
Scala also allows the following:

val xs = List(1, print(2), new MyClass)

for which it infers the type List[Any] which is probably not what one would expect, and may be masking an error as although Int, Unit, and MyClass all inherit indirectly from Any, it does not often make sense to store Unit in a List.

@dsaf
Copy link
Author

dsaf commented Mar 26, 2015

@aluanhaddad I would prefer the simple case support in C#7 to start rather than complete support in C#9.

@svick
Copy link
Contributor

svick commented Mar 26, 2015

@aluanhaddad

However, this could be addressed if the language supported intersection types.

How would that be implemented? AFAIK the runtime doesn't support intersection types (except for generic parameters with constraints). Are you suggesting that the runtime should be changed? Or would ICute with IExpensive be represented by something like Tuple<ICute, IExpensive> and then the compiler would automatically access Item1 or Item2 as needed?

@aluanhaddad
Copy link

@svick It wasn't so much my intent to suggest the addition of intersection types, as to provide a hypothetical context in which such type inferencing would make sense, and giving an example of how an existing language determines the type in such a scenario. I used the syntax IA with IB just as an example of how one might express such a type signature.

However, if such a feature would be implemented it would probably be part of a larger feature proposal to add Traits or Mixins to the language. I believe there are currently several such feature proposals. If Traits could be applied on a per instance basis, as in Scala, then this feature might be added as a way of referring to the type of such a instances.

@dsaf I would welcome the addition of the simple case as well. I know there was a plan at one point to add generic type inference to constructors, I am not sure what the status of that proposal is though. I remember that @gafter referenced it in a discussion on the codeplex site back in October but I cannot seem to find the actual proposal. Generic type inference for constructors would provide the functionality you desire.

@dsaf dsaf changed the title [C# feature] Support inferring type parameters of generic types in collection initializers [C# feature] Support inferring type parameters of generic types in constructors and collection initializers Apr 28, 2015
@dsaf dsaf changed the title [C# feature] Support inferring type parameters of generic types in constructors and collection initializers [C# feature] Infer generic type arguments in constructors and collection initializers Apr 28, 2015
@dsaf
Copy link
Author

dsaf commented Apr 28, 2015

@aluanhaddad You are right, I have created a separate issue for the simple case - it doesn't have to be specific to collections I guess #2319.

@alrz
Copy link
Contributor

alrz commented Jan 31, 2016

As far as I can tell, this proposal requires two features to work:

  1. Otherwise unresolvable simple names to resolve to a generic type
  2. Delayed type inference

First of all, List should be resolved to List<T> as long as there were no other generic/non-generic types in the scope. However, it can be disambiguated with diamond syntax. After that, type argument should be inferred at the first point that it was being used, e.g. Add method. Then it would be possible to use this feature with static methods as well, just like F#.

@Opiumtm
Copy link

Opiumtm commented Oct 12, 2016

Never take interfaces into consideration when inferring types.
Interfaces are form of multiple inheritance and multiple inheritance should always be treated explicitly.

@Pzixel
Copy link

Pzixel commented Jan 6, 2017

@Opiumtm you may never been working with LINQ and anonymous types, which returns something like IGrouping<<>f__AnonymousType0#11[System.Int32]>` and cannot be explicitely provided by user.

@CyrusNajmabadi
Copy link
Member

This is a language change request and is subsumed by the collection literals proposal here: dotnet/csharplang#5354. Closing this out.

@CyrusNajmabadi CyrusNajmabadi closed this as not planned Won't fix, can't repro, duplicate, stale Oct 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests