Roslyn: Proposal: Extended lightweight dynamic

Created on 22 Dec 2016  路  9Comments  路  Source: dotnet/roslyn

Extend "lightweight dynamic" (#3555) with method invocations, etc.

var r = obj.$Property;
var r = obj.TryGetProperty("Property");

var r = obj.$Method()
var r = obj.TryInvokeMember("Method", Array.Empty<Argument>());

var r = obj.$Method(arg: 1)
var r = obj.TryInvokeMember("Method", new[] { new Argument(name: "arg", value: 1) });

var r = obj.$[1];
var r = obj.TryGetIndexer(...);

TryInvoke, TryGetIndexer, etc could be convention based and not depend on a base class or interface.

This would be a lightweight compile-time alternative to System.Dynamic.DynamicObject.

Note: first use case could prefer an indexer as proposed in #3555 to be more useful with existing types.

If you just want a dynamic argument list:

var r = obj.Method$(arg: 1)
var r = obj.Method(new [] { new Argument(name: "arg", value: 1) })

Alternatively you could use #6949, e.g obj.M({ "arg": value });.

0 - Backlog Area-Language Design Language-C#

Most helpful comment

I'm not convinced that dynamic is as slow as everyone seems to assume it is. There are plenty of cases where it is more than sufficient.

All 9 comments

@alrz

How would you access a name/property that has a space or other invalid characters in it?

Maybe it would make sense to do something like this:

var r = obj.$["Some Property"];

Or even this:

var r = obj.$"Some Property";

That will get generated into the following:

var r = obj.TryGetProperty("Some Property");

How would you access a name/property that has a space or other invalid characters in it?

You cannot. The point of #3555 is to use identifiers as a shortcut for dictionary keys. I think in JS you will also need to use indexer syntax for non-identifier names.

@alrz Makes sense, thanks.

I'm not convinced that dynamic is as slow as everyone seems to assume it is. There are plenty of cases where it is more than sufficient.

@aluanhaddad Well it's more generalized approach, need no DLR and it's a compile-time feature so there's less plumbing involved, I _guess_ that this is where the _lightweight_ notion of it comes from, also, I think that both are useful in different circumstances.

@alrz You said we will need to use an indexer do you mean we will have to do something like this obj.$["Some Property"];?

How is failure to invoke handled? What are the return types?

@eyalsk No, it would resolve to obj.TryGetIndexer(" ... "). I updated OP to include this.

@bondsbw Unlike DynamicObject, there would be no runtime failure as in "bind failure", because this is translated at the compile-time, however, methods are free to return null (or throw) in case of not being able to handle the input. I'm thinking that #3555 should also implicitly cast to the target type, if any. so string r = s.$X; would translate to string r = s.TryGetProperty("X") as string or something like that.

@eyalsk thank you. That clarifies things.

@alrz how would that work? If I write something like
C# var r = obj.$Missing();
shouldn't that throw a RuntimeBinderException (or a lightweight dynamic equivalent)?

@aluanhaddad That makes sense only in a dynamic context. Missing is just a string passed to TryGetProperty (or an indexer as proposed in #3555), so it can't really be "missing" unless that method doesn't know how to handle it, in which case it is up to its implementation.

Was this page helpful?
0 / 5 - 0 ratings