Replies: 78 comments 1 reply
-
I propose reusing the |
Beta Was this translation helpful? Give feedback.
-
I'm not entirely sure whether the |
Beta Was this translation helpful? Give feedback.
-
In C++, all of qualified names are separated by |
Beta Was this translation helpful? Give feedback.
-
I think |
Beta Was this translation helpful? Give feedback.
-
Eliminates much of the verbosity benefits of the syntax. You'd be better off with the full lambda syntax. I do agree that there may be ambiguity with the existing |
Beta Was this translation helpful? Give feedback.
-
I don't really care about verbosity as much as allocations, but I see your point. How awful would |
Beta Was this translation helpful? Give feedback.
-
Well, I guess that it should actually be |
Beta Was this translation helpful? Give feedback.
-
@eyalsk I think it should work for static too: |
Beta Was this translation helpful? Give feedback.
-
@jnm2 Yes but dunno delegate seems a bit weird to me, maybe |
Beta Was this translation helpful? Give feedback.
-
@eyalsk Reminds me of my |
Beta Was this translation helpful? Give feedback.
-
@jnm2 Well, I don't know how I feel about this. :) |
Beta Was this translation helpful? Give feedback.
-
Data point: Just ran into a scenario where it would be extremely convenient to write |
Beta Was this translation helpful? Give feedback.
-
Is there any particular context where an aliased assembly name can be confused for a method reference?
Another datapoint: Java devs have had access to |
Beta Was this translation helpful? Give feedback.
-
You could just change the language such that method groups can also be converted to delegate signatures that match their open form (preferring closed form for backward compat), and you would not need any new syntax. You could simply write: Func<Foo, int> f = fooInstance.M; |
Beta Was this translation helpful? Give feedback.
-
@mattwar in |
Beta Was this translation helpful? Give feedback.
-
It seems like duplicating existing features through new ones would be just as validly be considered to be 'bloat' to me :) |
Beta Was this translation helpful? Give feedback.
-
That argument could just as easily be used against your |
Beta Was this translation helpful? Give feedback.
-
Would they though? You could certainly synthesize whatever you needed to represent that type in your assembly. You'd just attribute it as necessary to mark it as one of these unbound-delegates. Since a delegate is just a wrapper around an optional instance and a method-ref, you could always create convert between these guys as necessary. You could potentially observe this with object-identity. But that's solvable by just having the language say that object-identity isn't guaranteed across assemblies (similar to what is said about the types of anonymous-types). |
Beta Was this translation helpful? Give feedback.
-
Agreed. So why go a 3rd way now? |
Beta Was this translation helpful? Give feedback.
-
I can't imagine that being particularly efficient, though I can't think of an alternative without making delegates first-class.
At least with anonymous types, it's pretty clear what you're dealing with. I doubt most people would think to assign an instance of an anonymous type to a variable of an explicitly declared type. I know I'd certainly make the mistake of doing that with delegates, though. |
Beta Was this translation helpful? Give feedback.
-
That sounds like an IDE issue (something i have a passing familiarity with ;-)) We already provide ways to filter down completion lists. An easy way to look through all the top level language concepts available is with: -- Btw, this is great example of how C# works and how it is not OO. No one** complains that you have have to write: if (someExpr) { } else { } Instead of the much more OOy way: someExpr.if({ ... }, { ... }) // or
someExpr.if { ... } { ... } // or
someExpr.if({ ... }).else({ ... }) Yes, the more OOy way would be to express all program concepts and OO messages to the appropriate Os. But C# isn't pure OO (and many would probably not like it if it were). -- ** Ok, ok. I have heard complaints from smalltalk veterans that they actually would like it if C# were like this. Too bad, it's not happening. Compiler builtins don't try to be OOy. :) |
Beta Was this translation helpful? Give feedback.
-
WHy would be it be inefficient. It's just a struct wrapping two pointers. This is how Midori/M# did things BTW. :)
Why would that not be allowed? If you had a compatible "open delegate" instance, then assigning to one of .Net's nominal delegates seems like it would be something that would def be allowed. |
Beta Was this translation helpful? Give feedback.
-
Hmm... I suppose.
There's no such conversion at the moment between delegate types, as far as I'm aware. That'd need to be added--which is probably a good idea. |
Beta Was this translation helpful? Give feedback.
-
I would assume that if we ever had this concept of 'open delegate types' (or structural/non-nomimal delegate types), we'd do these conversions :) |
Beta Was this translation helpful? Give feedback.
-
Yes, that's what I'm pointing out. :P If I thought that issue weren't resolvable, I wouldn't have bothered writing a long post about the much-less-important syntax aspect, lol |
Beta Was this translation helpful? Give feedback.
-
@Zenexer Just a friendly advice, you should really consider making a new issue than discussing your ideas on a random issue. The original post that you made has almost nothing to do with the OP because you're not discussing the OP, you're opposing to what the language offers today, proposing alternatives and and go beyond that. p.s.
I do have to point out that this statement is actually incorrect and you're confusing multiple things in your post, it would have been weird if they weren't first-class citizen and how they are implemented has nothing to do with what they are at the language level. In the link you posted they refer to the existing delegate types not being first-class citizen in the language, two different things. @CyrusNajmabadi With all due respect, it's much better to tell the person to create a new issue and have a whole discussion there about whatever you guys are on about. |
Beta Was this translation helpful? Give feedback.
-
Sorry, that was unintentional. It started off as a short post about how to resolve the ambiguities created by the proposed syntax, but, as I was writing that, I kept uncovering issues with my own solutions. Three hours of research and writing later... Which reminds me: was there ever a consensus reached for handling the ambiguities created by properties? Specifically: public class A
{
public B Property { get; set; }
}
public class B
{
public int get() => 1;
}
var a = new A(); An ambiguity arises: var x = a::Property; // Is x a Func<B> or an Action<B>? I believe the proposed alternative was var x = a.Property::get; // Is x a Func<B> or a Func<int>? That was my original reason for proposing the introduction of Now that I think about it, this could work: var getter = a::Property.get;
var setter = a::Property.set; |
Beta Was this translation helpful? Give feedback.
-
For property accessor reference, considering the current standard ( int X { get; set; }
void M()
{
Action<int> getof = x => { };
getof(X); //runs the action or references the get accessor?
} The code above compiles today, but the same is also valid for int X { get; set; }
void M()
{
Func<int, int> nameof = x => 2;
var a = nameof(X); //a = 2
}
void N()
{
var a = nameof(X); //a = "X"
} That said, I think the suggestion is valid if the above demonstrated behavior is maintained. |
Beta Was this translation helpful? Give feedback.
-
Is this still an ongoing discussion? |
Beta Was this translation helpful? Give feedback.
-
Is it possible to also add a type to the BCL like below: struct PropertyReference<T>
{
public PropertyReference(...} { ... }
public T Get() { ... }
public void Set(T value) { ... }
// or
public T Property { get { ... } set { ... } }
}
void Foo(PropertyReference<int> propRef) { ... }
class Bar
{
int Property { get; set; }
}
var bar = new Bar();
Foo(bar.Property); // or something like that Basically, the idea is to have some syntax to bind to both get and set and pass that in one shot, and for C# compiler to auto-generate the code to construct this type. |
Beta Was this translation helpful? Give feedback.
-
Ported from: dotnet/roslyn#5444
Method References
Summary
A short syntax to denote open delegates and method references.
Motivation
Currently we can create closed delegates from static methods and non-static methods of a particular instance with a target-typed member access. But if we want to create a direct delegate from a non-static method without a particular instance, we will need to fallback to reflection and use
Delegate.CreateDelegate
. Furthermore, it's quite common for a lambda expression to do nothing but call a method or property accessor. In those cases, it would be clearer if we just refer to the method or property by name. Besides, the compiler could avoid generating double-invoking closures and directly reference the method itself.Proposal
Just like closed delegates, we will depend on target-typing to select the precise member to create an open delegate from.
The same syntax can be used to create delegate from property accessors,
The source type could be omitted if it can be inferred from the usage. This is specially useful with LINQ:
Which is equivalent to:
This has the same effect but not exactly equivalent to the following:
As it passes open delegates of
get_Employee
andget_Name
accessor methods.Note that the compiler can use
ldtoken
andGetMethodFromHandle
to supply aMethodInfo
as it does in expression trees.Variations
Constructor
CLR does not support constructor delegates, however, the syntax can be used to simulate that behavior:
Should be translated to:
The resultant lambda would have a parameter per each constructor argument that is passed directly.
If the constructor is overloaded, it will be selected based on the target delegate type with a chance of failure.
Operators
Additional sugar to create delegates off operators
Instance properties
Unlike methods, currently there is no way to create a delegate off a instance property e.g.
It's an open issue that what exact expression should be allowed in place of
foo
here.Events
Since events have identical signatures for both accessors, we probably should specifiy the accessor,
Alternatives
Alternatively, we could just optimize simple lambda expressions e.g.
x => x.Name
to an open delegate but the fact that it affects the existing code may or may not be desirable. Additionally, we should use the existing lambda syntax which is slightly more verbose than a type inferred method reference i.e.::Name
.Drawbacks
It might be the case that performance gain is not as significant as it is advocated here, but it directly depends on the generated code. The syntax, however, is a nice-to-have.
Beta Was this translation helpful? Give feedback.
All reactions