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

Proposal: "Lightweight Dynamic" aka Indexed Members #3555

Closed
gafter opened this issue Jun 17, 2015 · 18 comments
Closed

Proposal: "Lightweight Dynamic" aka Indexed Members #3555

gafter opened this issue Jun 17, 2015 · 18 comments

Comments

@gafter
Copy link
Member

gafter commented Jun 17, 2015

This was pulled from C# 6. Is there anything worth doing for the future?

The language feature is to take the syntax X!Y (or, alternately, X.$Y) to be a shorthand for X["Y"], and to add the syntax for object initializers { !Y = expr } (or { $Y = expr }).

This short explanation doesn't do it justice as a language feature; what would give it the most value would be APIs, such as a json library, that used such an indexer to enable you to navigate json objects with a more natural notation. One could even add further support in VS to give completion hints.

See also https://roslyn.codeplex.com/discussions/541566

@ljw1004
Copy link
Contributor

ljw1004 commented Jun 17, 2015

Here's a comparison of how dynamic looks in a common case, of JSON.Net. (Personally I prefer the second version. I've never understood the draw of the first.)

// (1) JSON.Net with dynamic:
dynamic d = Newtonsoft.Json.Linq.JObject.Parse("...");
string id = d.id;
int page = d.data.page;
bool complete = d.data.complete;

// (2) One non-dynamic option:
var d = Newtonsoft.Json.Linq.JObject.Parse("...");
var id = (string)d["id"];
var page = (int)d["data"]["page"];
var complete = (bool)d["data"]["complete"];

// (3) Another approach:
var d = Newtonsoft.Json.Linq.JObject.Parse("...");
var id = (string)d.SelectToken("id");
var page = (int)d.SelectToken("data.page");
var complete = (bool)d.SelectToken("data.complete");

@HaloFour
Copy link

Has it really been that much of a benefit for VB.NET?

Dim d = Newtonsoft.Json.Linq.JObject.Parse("...")
Dim id = CType(d!id, String)
Dim page = CType(d!data!page, Integer)
Dim complete = CType(d!data!complete, Boolean)

I programmed in VB for a number of years prior to .NET (and some after) and I generally made a point to avoid the ! operator as I thought that it muddled the purpose of the code.

@paulomorgado
Copy link

I have mixed feelings about this.

But I think it will generate better code than making everything dynamic while being explicit that those members being invoked are not real members.

@orthoxerox
Copy link
Contributor

I think forcing the classes to implement IDynamicMetaObjectProvider would be a better way. We get to use the same dot-notation with them and they are not restricted to using [].

@paulomorgado
Copy link

This feature is intended for objects that have an indexer with a string key.

It makes no sense to have to implement IDynamicMetaObjectProvider because these aren't truly dynamic objects in the C# sense.

@ghord
Copy link

ghord commented Jun 17, 2015

Without completion hints in VS, I feel it does not add enough value.
With some kind of completion provided by type at compile time, I think it would be great feature if you could use it like that:

var query = new Query("select id from table where parent_id=@parent");
query.$parent = 12; // completion for parent parameter
var result = query.Execute();
var id = result.$id; // Here we have VS completion for "id" field, maybe even id type inference.

I guess it would be similar to TypeProviders from F#

@SolalPirelli
Copy link

The JSON/SQL/... with autocomplete use case is fulfilled with F#-like type providers, which don't require any new member access syntax, and are quite a lot more powerful (and cooler!) than this. Without autocomplete, it's just another form of ExpandoObjects.

The main problem I see with this feature, regardless of purpose, is that it only works for string indexers that are also legal C# identifiers. It's not uncommon to see e.g. JSON with keys containing spaces, for instance. IMHO it's weird to have a feature that only works some of the time, depending on the shape of the data.

@HaloFour
Copy link

@SolalPirelli

The main problem I see with this feature, regardless of purpose, is that it only works for string indexers that are also legal C# identifiers. It's not uncommon to see e.g. JSON with keys containing spaces, for instance. IMHO it's weird to have a feature that only works some of the time, depending on the shape of the data.

Is it that common, or really a problem? It's not like JSON keys that aren't legal JavaScript identifiers can be treated like properties in JavaScript either.

@SolalPirelli
Copy link

Is it that common, or really a problem? It's not like JSON keys that aren't legal JavaScript identifiers can be treated like properties in JavaScript either.

It's not that common, but it happens; I've written clients for enough crazy APIs to see all kinds of horrible naming patterns. Another example is XML element names containing -.

@ljw1004
Copy link
Contributor

ljw1004 commented Jun 17, 2015

I've seen lots of json identifiers that have dots in them. For instance, https://dev.onedrive.com/README.htm

{
   "@content.downloadUrl":"...",
   "@name.conflictBehavior": "rename",
   "@odata.nextLink": "..."
}

@HaloFour
Copy link

@SolalPirelli As have I. It can be obnoxious. I guess my point is more that it is expected that the keys in these cases can only be valid identifiers and other languages that have this form of syntax have the same limitations.

JavaScript:

var x = json["case"];  // can't use reserved word
var y = json["some value"]; // can't contain space
var z = json["another-value"]; // can't contain hyphen

That said, I don't really see a lot of point to this kind of syntax. It seems like feature parity for the sake of feature parity. Do many VB.NET programmers actually make use of this feature today?

If there is a way to feed pseudo-member listings to Intellisense ala Type Providers that would be very nice, but I would imagine that same effort could also benefit proper indexers and dynamics as well.

@MgSam
Copy link

MgSam commented Jun 18, 2015

The problem: Weakly typed structures like JSON are kludgy to use in C# and have no autocomplete.

The issue here seems to be one of tooling, not of language design. If autocomplete can make educated guesses about what to suggest using the proposed syntax, it should also be able to do so using the existing indexer syntax, which has no constraints on what type of strings you can use. Adding a new syntax that comes with more drawbacks than the existing syntax is not a good idea.

Actually, I thought this was the consensus the C# 6 team reached as well as this was one of the first features jettisoned during that design process. You guys made the right decision at that time.

@pawchen
Copy link
Contributor

pawchen commented Jun 18, 2015

See this JSON response example of JIRA REST API, there are keys like "48x48", "sub-tasks"

@dsaf
Copy link

dsaf commented Jun 18, 2015

JSON might become less relevant the way XML did. Let's not add temporary trends into the language.

@bbarry
Copy link

bbarry commented Jun 19, 2015

What does this offer over improving intellisense on ["case"] structures?

The language feature is to take the syntax X!Y (or, alternately, X.$Y) to be a shorthand for X["Y"],

Only when Y is an identifier.

However if tooling could be improved such that [ provides intellisense for ["Y"], The identifier restriction no longer matters.

👎 on new syntax; 👍 on better tooling

@aluanhaddad
Copy link

@MgSam you hit the nail on the head.
Adding an additional syntax for accessing string indexable data structures is completely orthogonal to improving IDE tooling around the usage of those indexers.

Anyway, it seems to me that adding such tooling, which would be great if it could be made sufficiently reliable, would require a combination of both schema inference and flow analysis.

If we consider a tool like Resharper, it appears to use a combination of different heuristics, which I assume to be flow driven, in order to generate completion lists for dynamic and string indexable objects. The problem with this is that it is not a reliable feature. It is often right, but not always.

@chrisaut
Copy link

I was also under the impression that this was dropped (not for time constraints but because the consensus was that it was not a good idea).
I agree with @MgSam, especially this.

If autocomplete can make educated guesses about what to suggest using the proposed syntax, it should also be able to do so using the existing indexer syntax, which has no constraints on what type of strings you can use. Adding a new syntax that comes with more drawbacks than the existing syntax is not a good idea.

Furthermore I think it just doesn't add enough value, adding a different way of doing things should come with big benefits to overcome to "cost" of not only having to implement it, but of all developers who now have to add this to their mental model when reading code.

@CyrusNajmabadi
Copy link
Member

Closing this out. We're doing all language design now at dotnet/csharplang. If you're still interested in this idea let us know and we can migrate this over to a discussion in that repo. Thanks!

@CyrusNajmabadi CyrusNajmabadi closed this as not planned Won't fix, can't repro, duplicate, stale Nov 8, 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