-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Proposal: Collection, Anonymous and Function Types #7092
Comments
Seems to be too many things in one proposal here and many of them rely on other proposals that don't necessarily have a lot of traction. I think trying to make anonymous types public and faking "equivalence" will end up being way more trouble that it's worth. It only takes two dependencies with similar "public" anonymous types and a need to pass from one to the other for the voodoo to break down in very non-intuitive ways. I'm still very much of the opinion that if you want a public-facing type that you should declare a public-facing type and not rely on some kind of magic to coalesce inline declarations into some form of public contract. I don't even like the prospect of it happening with tuples. I don't see how the function type fixes the biggest problem with delegates and that being the lack of delegate type equivalence. Your syntax doesn't and can't fix the problem that I'm curious how the dictionary literal proposal will play out, but that probably belongs under #6949. List literals are probably a proposal unto themselves. The only real concern I have about them is that I don't think there would be a quick consensus as to what type the literal should be. C# devs would probably expect an array whereas JavaScript devs would probably expect a list. I'm not sure exactly what fixed-size arrays really buy and this would be easily confused with actual fixed-size buffers (#126) which are a very different beast. At best they could be a normal array and an attribute. Rather than trying to nail a lot of very individual validations one-by-one I'd rather see a bigger story around argument validation and metadata to drive analyzers, #119 except with focus as to how the rules are encoded in the assembly metadata. |
@HaloFour They all follow a common theme here, "new kind of types" so I decided to put them all in a single proposal. I don't mind opening new issues though. I think, rather, the existing anonymous types are more voodooish, the compiler does all the work to make type-safe anonymous types and then hide it from developer. It seems that the only real use case for anonymous types is to facilitate LINQ operators. I just tried to make them more useful and lessen the voodoo going on behind the scene. Besides, for type equivalence I think there exist some more intuitive ways to solve it but I was not capable of thinking them up. Your objection regarding "relying on some kind of magic to coalesce inline declarations into some form of public contract even with tuples" is likely to be considered beyond this discussion. ;) As mentioned before, double delegate invocation and delegate equivalence are not something that we can solve within the language, but having conversion implicitly handled by compiler is. Delegate declarations are way too ancient things that exist in the language, for a modern language, function type is an essential feature I believe. With method references, ref returns, capture lists, and all that jazz that is going to find its ways to the language I think function types can play a key role here. #6949 is going in a different direction I think, when it has been said that it is going to use whatever type named Motivation behind fixed-size arrays as proposed here is that arrays which created by |
👍, @HaloFour . |
Anonymous types exist largely for projections, yes, and because of that they're not supposed to leak to the public. Any solution to try to make them public would be very messy. This is why tuples will rely on BCL provided structs. Given how simple it will be to define record classes I don't see a need for inline public anonymous type declarations. Considering that the double delegate invocation thing comes up every time inferred delegate types come up I think that is the reason that there hasn't been an attempt to solve it in the language. I took @gafter 's comment in #6949 to mean that the prototype was designed around |
What would be the type of a function that computes a cross product of two vectors represented as tuples, |
@orthoxerox or |
@alrz my point was that |
@orthoxerox Maybe. Then |
@alrz the former, as in all ML languages. |
I have to give up function types too, because they also suffer from type equivalency issue just like anonymous types. As long as structural types/delegates are not supported, this is not possible. As for collection types, I'd rather close this in favor of #6949. "we need to have one issue per issue." |
Collection, Anonymous and Function Types
Following other proposals regarding introducing new kind of types, including slices (#120), tuples (#347) and intersection types (#4586), I want to propose language features for some other types mentioned in the following table.
{T M1, U M2}
(T: U)
T{}
T(U)
Note that these are not the exact proposed syntax and they are meant to be altered based on feedback.
Anonymous Records
As it turns out, anonymous types caused a mass confusion. I see people try to use
dynamic
andInternalsVisibleToAttribute
to access anonymous types' members within or across assemblies which is not a good idea IMO. I think intention of anonymous types is not obvious to people coming from other languages like JS and they just carelessly use them for various purposes which are not meant to be used for. Named tuples may address some of these use cases but still, since member names can be altered or erased (e.g. in patterns) they might be not a good option in some other contexts. The lack of ability to pass type-safe anonymous types around, sometimes cause to declaring trivial classes or even using reflection. To keep the best of both worlds, I propose anonymous records which are actually same as anonymous types in a sense, and they behave like tuples or records in the other.From now on, anonymous-object-creation-expression returns a anonymous-type, for example:
Class generation for these types remains the same for existing anonymous types, with the difference that if an assembly expose an anonymous record type, the generated class will be emitted as
public
. If some other assembly interact with these types, compiler would reuse the generated class and wouldn't generate a new one. For inter-assembly interactions, a new object would be created to be used for the target anonymous type. Since these classes are actually records, they can be used with thewith
expressions and can be deconstructed with a property-pattern without a type, for example,No conversions between various types of anonymous records would be permitted, unless they possibly implement interfaces as proposed in #13.
Function Types
The behavior of existing delegates also raised some questions: why it's not possible to cast identical delegates to each other, i.e.
Action<object, EventArg>
is not the same asEventHandler
, in despite of the fact that they are expected to be. From spec:But still, they do care if you want to cast themselves to each other! It's like a sore spot that never seems to go away.
While
Action<...>
andFunc<...>
delegates can cover almost all use cases, still, they cannot be used withref
andout
parameters, and you have to declare your own delegate types. Function types can address these issues, so you don't have to declare or use a specific delegate type just for these reasons.Function types would translate to regular delegates but it is proposed that the following can be part of a function type for further compile-time validation and type safety:
ref
returns (Proposal: Ref Returns and Locals #118): To indicate that the function hasref
return.ref
/out
parameters: To indicate that the function hasref
/out
parameters.Syntax
Examples
List and Dictionary Types
To make #6949 more generally usable, I propose a language feature for list and dictionary initialization which also can be used with other types like
JObject
,In the last example, nested maps will infer the type of the parent, in this case
JObject
. For lists, the target would have anAdd
with the second parameter of a non-abstract type that implementsIEnumerable
likeJArray
to infer.This has some interactions with #2319 so if you want to create another class you should be able to omit type parameters, like
If the context already provides type information, such as a function argument or an already typed variable, you can create an empty list or dictionary with
[]
or{:}
respectively.Syntax
The text was updated successfully, but these errors were encountered: