-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Use lambdas to implement interfaces and abstracts classes that have a single abstract method. #4801
Comments
What's the point? You can already use a delegate type for that. And if you really want to have an interface, you can use both, see for example the |
I see some level of similarity with #13. obj.Call(new { Method = () => { /* work */ } }); |
What happens if an abstract class has a private/protected field/property/method - will it be possible to access |
@jmaine Can you provide some motivation for why this change would be worth taking in the language? Changing the lambda conversion like this would be a breaking change. |
Why would it be a breaking change? |
@jmaine because there are existing types that are single-method interfaces and abstract classes. Therefore we would be adding a conversion that did not exist to existing code. That may make some methods that were previously inapplicable applicable. That could make some method calls that used to work fine into ambiguity errors. For example public interface ISAM { void M(); }
public delegate void DEL();
public class Zippy
{
public static void Pinhead(ISAM sam) { }
public static void Pinhead(DEL del) { }
}
class Client
{
public static void Main(string[] args)
{
Zippy.Pinhead( () => {} );
}
} This is code that would compile and run just fine today, but under the proposed change it would be ambiguous (an error) because both My question remains: what is your motivation for this change? How would it improve the plight of programmers? Or are you just suggesting it because Java did things that way? When I proposed the addition of lambda expressions to Java I specified it this way* because, among other reasons, Java does not have the concept of *I specified the lambda conversion for Java to single-method interfaces only, not abstract classes, but the reason for that is a longer story. |
This can be useful for interfaces that might be implemented by classes (OOP) but you might prefer a concise syntax to inline the implementation (FP), so delegates are not an option here. Without this feature you might define two overloads and wrap the delegate in a special class which causes double invocation. Local classes (#9523) could be an alternative approach but still they are nothing like a single lambda expression. And with capture lists (#117), we can simply control captured state in a lambda expression. There would be no such feature in a local class. I'll also note that with #258 you can use this feature with more and more interfaces. As for backward compat we can use an attribute like // examples
interface IIterable<out T> {
IIterator<T> GetIterator();
}
interface IIterator<out T> {
T? Next();
}
interface IHandler<in T> {
bool Handle(T value);
}
// OOP style
class Node : IHandler<Message> {
Node() {
// FP style
RegisterHandler(arg => { ... });
}
}
// OOP
class List<T> : IIterable<T> {
// FP
public IIterator<T> GetIterator() {
return () => { ... };
}
}
// inline an iterable and iterator!
Method(() => () => { ... }); Also, sometime a delegate doesn't make much sense, public delegate bool Iterator<T>(out T value); Since C# is an object-oriented language in the first place (with functional features) this can be a useful addition to take advantage of best of the both worlds. Can you please consider reopening this? Thanks! |
The idea that the presence of an attribute in source would change the semantic meaning of an expression seems like a bad idea. I am having a hard time imagining any places in my own code or code I've seen where this would improve things. As the original author of the "single method functional interfaces" approach for Java that ended up being taken into that language, I have a deep appreciation for its value in Java. I am just having a hard time seeing how any effort in that direction for C# would make anybody's life easier. |
@gafter I think it would be a nice feature when you are mixing functional and OO paradigms (which seems to be the direction that C# is following), a delegate cannot be implemented with a class and an interface is not compatible with a lambda expression. Anywho, I think I've made my point, if you don't see any value in here, I should probably count on local classes in these situations. :) |
You can't do |
@svick My use case is the other way around, when you have an interface you will have to implement it. there is no way to work this around. I've seen classes like // this can't be a delegate because you might need to implement this
interface IHandler<in T> { bool Handle(T value); }
// (1) boilerplate class
class DelegateHandler<T> : IHandler<T> {
readonly Func<bool, T> handler;
public DelegateHandler(Func<bool, T> handler) { this.handler = handler; }
// (2) double-invocation
bool IHandler<T>.Handle(T value) => handler(value);
}
void RegisterHandler<T>(IHandler<T> handler) { ... }
// (3) additional overload
void RegisterHandler<T>(Func<T, bool> handler) => RegisterHandler(new DelegateHandler<T>(handler)); A lambda expression, specially in IIterator<T> GetIterator() {
return () => { ... }; // YAY
} After method references, this is the second feature that I missed from Java. |
Use lambda's to implement interfaces and abstract classes that have a single abstract method defined.
Example interface.
Example method declaration:
Using a lambda to implement it.
The text was updated successfully, but these errors were encountered: