Closed nvivo closed 8 years ago
I like the idea. Although anonymous types aren't meant to be passed outside the scope where they're created, interfaces are all about the contract so it doesn't matter much that the implementation is compiler-generated.
Per your suggestion about methods, it looks like C# 6 already blurs the line between methods and delegates (from a syntax standpoint), so maybe it's not such a far-fetched suggestion.
The reason anonymous types are not passable outside the scope where they are created is due to a lack of unification of types across assemblies in the runtime, not a design philosophy. Giving anonymous types an interface is a good idea. I believe it was proposed during the design for anonymous types but was outside the intent of the feature at the time.
This proposal seems related to object expressions in F# or anonymous inner classes in Java, both of which let you specify class implementations right when you new the objects up.
You could certainly imagine an evolution of anonymous objects in C# that would combine the current behavior with the ability to inherit classes, implement interfaces and supply member implementations.
Thinking out loud here, it seems that I could break my proposal in two:
Once the first is achieved, the second one should be straightforward.
To me, it is clear the idea is very useful and would reduce drastically the number "dumb" classes I need just to return models in interface driven code.
But it raises some questions:
new {
// new modifier keyword?
readwrite Name = "foo",
readwrite string Name,
// no types, always infer from the value?
readwrite Name = default(string),
// no value implies it will be set later, hence writeable? - looks strange
string Name;
// borrow syntax from real properties?
string Name { get; set; },
Name { get; set; } = "initial value",
// or imply the get and require only the set?
string Name { set; },
Name { set; } = "initial value",
}
interface IPerson {
string Name { get; set; }
bool IsDeceased { get; set; }
}
IPerson GetPerson() {
return new {
Name = "John"
};
}
This would create some form of "duck typing", making like implementing one-time used interfaces easier.
interface ISystemClock {
DateTimeOffset Now()
}
iocContainer.Resolve<ISystemClock>().With(new { Now() => DateTimeOffset.Now });
I duped this (as linked above), with an alternative syntax.
+1
+1
+1
@nvivo Are you requesting specifically interface implementations or subtyping as well?
Depending on that #1728 might be a duplicate.
Also what do you mean by saying "interface driven design"?
Relevant quote:
http://www.jot.fm/issues/issue_2005_07/article1.pdf
Note that as generalizations, interfaces compete with abstract classes. In fact, in practice interfaces and abstract classes are sometimes used as if they were the same concept. However, since abstract classes have the potential to pass on implementation to their subclasses, they should be used if (and only if) the relationship to the subclasses is genetic, i.e., if it is (or at least could be) based on the inheritance of internal structure, that is, implementation. If on the other hand the relationship is based on pure function (or, weaker still, on sameness of protocol), interfaces should be used. For instance, a linked list and a dynamic array would normally not be genetically related (i.e., have no common pieces of implementation), yet they share the interface of lists (specifying sequential access to their elements).
Note that records (#206) can implement interfaces. I think that satisfies the underlying need of this request.
@gafter Can records be declared within method body? I think this request is about not polluting the namespaces and creating explicit named types, rather than creating immutable classes with compact syntax. I believe these are different.
+1
As anonymous classes are created with only getters available and only in the current scope this feature might be non-trivial to implement.
But implementation can happen in 2 stages, 1 for getter-only interfaces and 2 for getter and setter + methods.
I would say implementing only interfaces containing property getters would be a huge improvement and should not change anonymous constructor code apart from adding inheritance to the anonymous class.
Inheritance syntax should be explicit and any setter or method on the interface or missing property on the anonymous implementation should trigger an error:
interface IPerson
{
string Name { get; }
bool IsDeceased { get; }
}
interface IEmployee
{
string Boss { get; }
}
IPerson GetPerson()
{
return new : IPerson, IEmployee
{
Name = "John",
IsDeceased = true,
Boss = "OK",
ExtraProperty = 123
};
}
I am skeptical of the property implementation syntax, I think it should be something like
return new : IPerson, IEmployee
{
Name => "John",
IsDeceased => true,
Boss => "OK",
ExtraProperty => 123
};
or
return new : IPerson, IEmployee
{
Name { get; } = "John",
IsDeceased { get; } = true,
Boss { get; } = "OK",
ExtraProperty { get; } = 123
};
because we are defining a type that implements the properties of the interfaces, where as in the case of anonymous types, the compiler is generating a type definition for us based on the names and values of the instantiation expression.
+1
Also thinking out loud here.
What about methods? One thing I've done for mock objects (without a mocking framework) in the past is to store a delegate that has the matching signature in a private field and invoke that from the interface. E.g.
interface ICustomer {
string Name { get; }
string Surname { get; }
bool IsValid();
}
return new ICustomer() {
Name = "Jim",
Surname = "Bob",
IsValid = () => true
};
This would roughly compile to:
class ICustomerAnyonymousType {
public string Name { get; set; }
public string Surname { get; set; }
public Func<bool> IsValidImplementation { get; set; } // Or a private field
public bool IsValid() {
var impl = IsValidImplementation;
if (impl == null) throw new NotImplementedException();
return impl();
}
}
return new ICustomerAnyonymousType() {
Name = "Jim",
Surname = "Bob",
IsValidImplementation = () => true
};
What about default values? I might not want to provide an implementation for a method or omit a property. Possibly:
return new default ICustomer() {
Name = "Jim"
};
Surname
would return null
, and IsValidImplementation
would be set to null
(causing a NotImplementedException
). If default
is omitted all members must be provided (else there will be compile failure).
Unit tests and mocking. For trivial scenarios (not involving abstract or sealed classes) you could mock your objects as follows:
[Fact]
public void DisplayCustomer_ValidateCalled()
{
var validateCalled = false;
var customer = new ICustomer() {
Name = "Jim",
Surname = "Bob",
IsValid = () => validateCalled = true
}
sut.Display(customer);
Assert.True(validateCalled);
}
[Fact]
public void DeleteCustomer_Deleted()
{
var customer = new default ICustomer() {
Name = "Jim",
Surname = "Bob"
// Omit IsValid because it is never called.
// NotImplementedException would be thrown if it was
// somehow called.
}
sut.Deleted(customer);
Assert.Null(sut.GetCustomer(customer));
}
@jcdickinson
return new ICustomer() { Name = "Jim", Surname = "Bob", IsValid = () => true };
It's not clear that you're initializing a property of type Func<bool>
or implementing the method. I think this should be done in a more explicit way like:
return new ICustomer {
public string Name => "Jim";
public string Surname => "Bob";
public bool IsValid() => true;
};
@alrz +1. Just use a comma for consistency. Isn't the return type+visibility redundant (unless internal interfaces make an appearance)?
return new ICustomer {
Name = "Jim",
Surname = "Bob",
IsValid() => true,
Foo = bar,
Baz() => false
};
This looks more like a initialization block rather than class declaration. Also it could be implemented as a nested local type (#259) so naturally you would expect anonymous classes as well:
return new BaseClass() {
public override bool IsValid() => true;
...
};
PS: comma was a typo, sorry.
Within context of this issue/feature it's about anonymous types and we should likely extend syntax instead of breaking existing syntax.
@arlz, these two look exactly the same to me:
IsValid() => true
public override bool IsValid() => true
adding modifiers doesn't change that, only makes more verbose.
@nvivo I think @alrz is bringing in inspiration across from #259, which could succeed/replace this feature - but that has already been specced over on that issue. I prefer the more succinct syntax, like you, as anything more is entirely redundant and doesn't look like the current anonymous types at all.
I'm talking about a more general feature like "implementing interfaces anonymously" instead of "anonymous types implementing interfaces". I borrowed all this from Java, though.
It anonymity really important? Compared to local (within a block) class declaration as an alternative way of handling this. It is nice that this lets you stay in an expression context, it is true, but I do not think the use cases are really simplified much.
It anonymity really important?
For Linq I'd assume it would be crucial.
public IEnumerable<ICustomer> GetCustomers() {
return from c in db.Customers
select new {
Name = c.Name,
Surname = c.Surname
};
}
In addition:
Does inventing new syntax here for anonymous-but-no-so-anonymous-types add anything at all? Even just one thing? Versus adding either nothing (if method declarations are not supported) or re-using the lambda grammar (if method declarations are supported); both also have significantly less keystrokes, significantly less indentation and are far easier to human-parse. Less syntax makes a language good, not more. Once you have added syntax you can never remove it, in opposition: using existing syntax should be largely familiar to experienced developers.
We have no expectation of ever doing anything like this.
That's disappointing.
Here's an example that came up today. Let's say we have some interface IParseMessages
:
interface IParseMessages
{
bool Parse(IMessage message);
}
Now we want to be able to add other stages to the parsing pipeline (think something like the handlers in ASP.NET), which can decide whether or not to invoke the "base" message parser. None of these handlers know anything about each other (we can't just link them all together when we write them). We could have a type like this:
public interface IMessageHandler
{
bool Parse(IMessage message, Func<IMessage, bool> inner);
}
The IMessageHandler
can now check the message and then decide whether or not to call onto the inner
handler.
Something that would be useful here would be to be able to fuse two message handlers together to form a new handler:
public static class MessageHandlerExtensions
{
public static IMessageHandler Then(this IMessageHandler derived, IMessageHandler baseImpl)
=> new ComposedMessageHandler(derived, baseImpl);
private sealed class ComposedMessageHandler : IMessageHandler
{
private readonly IMessageHandler _derived;
private readonly IMessageHandler _baseImpl;
public ComposedMessageHandler(IMessageHandler derived, IMessageHandler baseImpl)
{
_derived = derived;
_baseImpl = baseImpl;
}
public bool Parse(IMessage message, Func<IMessage, bool> inner)
=> _derived.Parse(message, msg => _baseImpl.Parse(msg, inner));
}
}
Now, if we have a list of IMessageHandler
s we can combine them all with something like (depending on what order you want them applied) handlers.Aggregate((d, b) => b.Then(d))
. (AKA, IMessageHandlers
are monoidal).
You might notice that that's a lot of typing. It would be nice to be able to write this instead, replacing all the code in the last block (using my proposed syntax):
public static class MessageHandlerExtensions
{
public static IMessageHandler Then(this IMessageHandler derived, IMessageHandler baseImpl)
=> new IMessageHandler with {
bool Parse(IMessage message, Func<IMessage, bool> inner)
=> derived.Parse(message, msg => baseImpl.Parse(msg, inner));
};
}
Aside: compare the F# which would be something like:
let combine (derived : IMessageHandler) (baseImpl : IMessageHandler) =
{ new IMessageHandler with
member __.Parse msg inner =
derived.Parse msg (fun m -> baseImpl.Parse m inner) }
Finally, we then need a way to augment an IParseMessages
with the combined IMessageHandler
, to produce a new fused IParseMessages
that we can pass around. In current C# this could be something like:
public static class MessageParserExtensions
{
public static IParseMessages Augment(this IParseMessages me, IMessageHandler handler)
=> new AugmentedMessageParser(handler, me);
}
sealed class AugmentedMessageParser : IParseMessages
{
private readonly IMessageHandler _handler;
private readonly IParseMessages _impl;
public AugmentedMessageParser(IMessageHandler handler, IParseMessages impl)
{
_handler = handler;
_impl = impl;
}
public bool Parse(IMessage message) => _handler.Parse(message, _impl.Parse);
}
Using the proposed syntax this could be reduced to the much smaller:
public static class MessageParserExtensions
{
public static IParseMessages Augment(this IParseMessages me, IMessageHandler handler)
=> new IParseMessages with {
bool Parse(IMessage message) => handler.Parse(message, me.Parse); };
}
Again, to compare with F# this would be:
let augment (me : IParseMessages) (handler : IMessageHandler) =
{ new IParseMessages with
member __.Parse msg = handler.Parse msg me.Parse}
I think this reduction in boilerplate would be very useful.
@Porges A lot of that boilerplate could be also removed by using a record
(part of #206).
It anonymity really important? Compared to local (within a block) class declaration as an alternative way of handling this. It is nice that this lets you stay in an expression context, it is true, but I do not think the use cases are really simplified much.
@gafter Are local type declarations still on the table? To me this is all about scoping.
In addition to scoping, I think capturing generic parameters could make this quite useful.
@aluanhaddad #9523
@alrz Thanks!
I've literally wanted this feature for years... If it worked then say goodbye to fakes, mocks and generated decorators!
This might give new lease of life to anonymous types since, as far as I can tell, they're about to be completely superseded by tuples. Giving them the ability to implement interfaces would give them a reason to continue existing.
I does not have to be perfect , it is anonymous types after all , i think implementing the interface geter without extra syntax like in the (t00 commented on Jul 24, 2015) cover 90% of the day to day need.
the idea is not to have full functional class, to do that just use a private class, we need to have ability to pass data when interface required, just like what we do in anonymous type in linq ,if the code try to consume the set method ,show an error or throw an Exception at run time, just like anonymous types.
tuple that can't implementing interface, will not solve the problem.
I still think this is a very required feature, but this issue has been closed and I don't believe the team will respond this issue again.
Someone with time to discuss should open a new issue proposing a simpler version of this and see what can get out of it.
This would be great to implement multiple action callbacks.. Image a class which downloads a file: Callback Interface:
public interface IDownloadResultHandler {
void Success(string path);
void Fail();
}
Class:
public class FileDownloader {
public static void Download(string path, IDownloadResultHandler callback) {
// starts download on a second thread and returns but keeps handle to callback
....
}
internal static void downloadThread() {
...
if(success) {
this.callback.Success(pathOfFile);
}
else {
this.callback.Fail();
}
}
}
Later on this could be used like this
MyConsole console = new MyConsole();
FileDownloader.Download("/path/to/file", new : IDownloadResultHandler {
Success() { console.Write("Success"); }
Fail() { console.Write("Failed.."); }
});
Currently one has to implement a seperate class which implements the interface and pass the environment via a constructor parameter or inject it via dependency injection..
Having anonymous Implementations of interfaces could save us from a lot of boilerplate code.. Furthermore "Callbacks" could explicitly state if they support a different functionality by implementing a interface or not!
I'm going to post another example just 'cause.
Here's some C#:
public Sink<TIn, TResult2> MapResult<TResult2>(Func<TResult, TResult2> projection)
=> new MappedResult<TResult2>(this, projection);
private sealed class MappedResult<TResult2> : Sink<TIn, TResult2>
{
private Sink<TIn, TResult> _sink;
private Func<TResult, TResult2> _projection;
public MappedResult(Sink<TIn, TResult> sink, Func<TResult, TResult2> projection)
{
_sink = sink;
_projection = projection;
}
public override ActiveSink<TIn, TResult2> Open() => new Impl(_sink, _projection);
private sealed class Impl : ActiveSink<TIn, TResult2>
{
private ActiveSink<TIn, TResult> _sink;
private Func<TResult, TResult2> _projection;
public Impl(Sink<TIn, TResult> sink, Func<TResult, TResult2> projection)
{
_sink = sink.Open();
_projection = projection;
}
public override TResult2 Result => _projection(_sink.Result);
public override void Dispose() => _sink.Dispose();
public override Task ProcessChunk(ReadOnlySpan<TIn> span, CancellationToken cancellationToken)
=> _sink.ProcessChunk(span, cancellationToken);
}
}
Here's the exact same thing using object expressions in F#:
member me.MapResult (projection : 'TResult -> 'TResult2) : Sink<'T, 'TResult2> =
{ new Sink<'T, 'TResult2>() with
override __.Open() =
let activeSink = me.Open() in
{ new ActiveSink<'T, 'TResult2> with
override __.Dispose() = activeSink.Dispose()
override __.ProcessChunk c ct = activeSink.ProcessChunk c ct
override __.Result with get() = projection activeSink.Result
}
}
Being able to close over variables in anonymous type definitions cuts down on a lot of boilerplate.
By comparison, here is the equivalent Java (with anonymous classes):
public <TResult2> Sink<TIn, TResult2> MapResult(Function<TResult, TResult2> f)
{
Sink<TIn, TResult> me = this;
return new Sink<TIn, TResult2>() {
public ActiveSink<TIn, TResult2> open() {
ActiveSink<TIn, TResult> activeSink = me.open();
return new ActiveSink<TIn, TResult2>() {
public TResult2 result() { return f.apply(activeSink.result()); }
public void close() { activeSink.close(); }
public void processChunk(TIn[] c) { activeSink.processChunk(c); }
};
}
};
}
And here's a hypothetical "C# with anonymous classes/object expressions":
public Sink<TIn, TResult2> MapResult<TResult2>(Func<TResult, TResult2> f)
{
var me = this;
return new Sink<TIn, TResult2> with {
override ActiveSink<TIn, TResult2> Open() {
var activeSink = me.Open();
return new ActiveSink<TIn, TResult2> with {
override TResult2 Result => f(activeSink.Result);
override void Dispose() => activeSink.Dispose();
override Task ProcessChunk(TIn[] c, CancellationToken ct)
=> activeSink.ProcessChunk(c, ct);
};
}
};
}
I've been working with Xamarin for Android recently, and because the underlying API is Java based, you're generally expected to pass in an interface implementation where typical C# conventions would use delegates or lambdas. In Java this is simple: use an anonymous class. In C#, you end up creating multiple unnecessary classes and it's very cumbersome.
We have no expectation of ever doing anything like this.
Well, boo to you.
Local type declarations are still on the table.
The most value I ever got from anonymous types in Java was a series of counterintuitive examples for the book Java Puzzlers.
I have never written Java, so am I missing something? I still really want this for C#.
I don’t know what you may be missing, but I believe that local class declarations give you the full power in a much more readable and clear form.
I'm willing to give that a try first.
@gafter Are there local classes in C#? Or this is a future feature? I agree that local classes would make anonymous interface implementations redundant.
@jnm2 that´s not really the same thing.. anonymous types implementing an interface would allow you to pass them as a reference to multiple callbacks to a long running action / task.. Such a pattern is heavily used in Android in Java.. There are typically multiple things that could happen if you trigger some asynchronous actions.. If you only have one callback/delegate you have to have multiple parameters which are not used in all cases, passing an object which implements functions for that cases looks much cleaner / is more readable.
@Spacefish And well I know it. I was answering @jbtibor's question, "Are there local classes in C#? Or this is a future feature?"
@gafter
I don’t know what you may be missing, but I believe that local class declarations give you the full power in a much more readable and clear form.
But with unnecessary boilerplate, even by Java standards. In my experience local type declarations are nearly non-existent in the Java ecosystem, but anonymous classes are exceptionally common. This was especially true leading up to Java finally getting lambdas. If you look at any of the helper packages for Java that deal in functional concepts or callbacks they all use anonymous types, including those from Google, Netflix, Apache, Amazon, etc., both internally and in any example they provide for using their APIs.
I could probably count the number of times I've seen local declarations in the wild on one hand, at best. The only times I've ever reached for them myself was to emulate closures in lambdas due to Java forcing all enclosed locals to be effectively final. With Java 10 that's no longer necessary and I will refactor all of that code to using anonymous classes instead.
public IDisposable Foo() {
class Foo : IDisposable {
public void Dispose() {
Console.WriteLine("Disposed!");
}
};
return new Foo();
}
vs.
public IDisposable Foo() => new IDisposable {
void Dispose() => Console.WriteLine("Disposed!");
};
There's nothing unreadable about that second example. If anything I think it does a much better job of focusing on what it actually does.
@gafter
Furthermore, if Java/Android interop is given as one of the reasons for adopting default interface members (of which I am in favor, regardless of the justification), then I can state that the same interop is a good reason to adopt anonymous classes.
As @errorx666 stated, Android dev is interface-driven for callbacks. This makes them cumbersome to use from C# as you have to declare an entire separate class. Local types help, but that's still a lot of ceremony to declare and instantiate to effectively emulate what would be an exceptionally verbose lambda. To improve that situation from C# I would recommend that anonymous types are considered. Even better would be to allow lambda syntax with interfaces with exactly one required method (or also expand that out to abstract types, like Scala supports). Incidentally, poking at the Android docs, they clearly favor anonymous classes also.
that the same interop is a good reason to adopt anonymous classes.
Are there public APIs in Java that have anonymous types?
@gafter
Are there public APIs in Java that have anonymous types?
No, there are public APIs throughout Java and the Java ecosystem that expose interfaces for use as callbacks, and the idiomatic (and natural) approach to implementing them is via anonymous types.
https://github.com/google/guava/wiki/FunctionalExplained https://hc.apache.org/httpcomponents-asyncclient-ga/quickstart.html https://commons.apache.org/proper/commons-functor/examples.html https://github.com/Netflix/Hystrix/wiki/How-To-Use#Reactive-Execution http://reactivex.io/documentation/operators/filter.html https://developer.android.com/guide/topics/ui/ui-events https://developer.android.com/guide/topics/location/strategies https://docs.oracle.com/javafx/2/events/handlers.htm https://docs.oracle.com/javase/7/docs/api/java/beans/EventHandler.html http://netty.io/wiki/user-guide-for-4.x.html#wiki-h3-9 https://jersey.github.io/documentation/latest/rx-client.html https://github.com/AsyncHttpClient/async-http-client#using-custom-asynchandlers
I honestly think you'd find it pretty difficult to find API docs that would suggest implementing callback interfaces using local types over anonymous types.
@RUSshy See the comment above: https://github.com/dotnet/roslyn/issues/13#issuecomment-173413281
We have no expectation of ever doing anything like this.
Also, this kind of issue now belongs to the csharplang repo, and there is a very similar request already opened there: https://github.com/dotnet/csharplang/issues/1542.
It would be very useful if C# anonymous types could implement interfaces, including methods. This would make a huge difference when developing using interface driven design. It would also allow for very easy mocking in unit tests.
In TypeScript and other dynamic languages, this has proven to be really useful and reduces a lot of boilerplate code.
It seems that implementing this in C# wouldn't break any rules as anonymous types are already classes internally, and the compiler could just make it implement the interface and use the same rules for checking type.
The only issue I can think right now is the method implementation. How to differ between a method and a property that is a delegate:
It seems that from the perspective of the C# consumer it wouldn't make much difference, as both can be called using the same syntax (
obj.Bar()
orobj.Baz()
), but the compiler needs to know this.This could be solved by either adding a new syntax to this implementation:
Or by just defaulting to methods unless the interface calls for a property. That would make the first example with the same code valid, and I guess would make the syntax better.