[Feature Request] Interfaces: attribute signature support #944
Replies: 45 comments
-
If I have an object and all I know about it is that it is an |
Beta Was this translation helpful? Give feedback.
-
What is an actual use case for this? How do you propose any of this actually work in the CLR? Members require names. Interface implementation requires overrides to be set at compile time in the IL metadata. |
Beta Was this translation helpful? Give feedback.
-
Is this just intended to be syntax sugar for reflection, e.g. Making it an interface pushes it beyond simple reflection and would affect overload resolution, generic type parameter constraints, and more which would require CLR changes (as @HaloFour alluded to). Perhaps #807 can inspire a different way to achieve that goal: if (foo.DoSomethingUsefulOnMyOwn(string) is [TargetMethodByInterfaceAttribute]) |
Beta Was this translation helpful? Give feedback.
-
@jnm2 Its not only an as an example of how calls to such methods can take place in AOP, check: aspectize @HaloFour eg: interface ILoggable
{
string LogName { get; }
[WriteLog]
void *(*);
}
public class Car : ILoggable
{
public string Name { get; set; }
public string ILoggable.LogName
{
get { return string.Format("Car.{0}", Name); }
}
[WriteLog]
public void Move(int meters)
{
//AOP Module will inject a logwrite-beginn call here with Member name as appendix
// Do Some Stuff
//AOP Module will inject a logwrite-end call here with Member name as appendix
}
public void Save()
{
// Do Some Stuff
}
[WriteLog]
public void Delete()
{
//AOP Module will inject a logwrite-beginn call here with Member name as appendix
// Do Some Stuff
//AOP Module will inject a logwrite-end call here with Member name as appendix
}
}
// COMPILE Error! Programm does not implement Interface Member with Attribute [WriteLog]
public class Truck : ILoggable
{
public string Name { get; set; }
public string ILoggable.LogName
{
get { return string.Format("Truck.{0}", Name); }
}
public void Move(int meters)
{
// Do Some Stuff
}
public void Save()
{
// Do Some Stuff
}
public void Delete()
{
// Do Some Stuff
}
} |
Beta Was this translation helpful? Give feedback.
-
@halittiryaki I think that's not what interfaces are for. And if you want to have custom diagnostics, I think the right way is to create a custom diagnostic analyzer, not try to make the compiler do the work for you (which it will never do perfectly). |
Beta Was this translation helpful? Give feedback.
-
I don't think that it's helpful trying to mix aspects and interfaces. They have very different concepts. None of this explains how you intend for this to work in the CLR, or how any of the AOP logic is actually injected into the methods. The LDM has discussed AOP scenarios before and the proposal intended to handle that is source generators, #107. |
Beta Was this translation helpful? Give feedback.
-
@svick @HaloFour As you (with source generation) and @svick (with code analysis) pointed to the proper direction, it would be a Roslyn task, before IL generation happens. To simply tell the developer:
As mentioned, this idea came when designing an AOP module but such a feature would most importantly, affect the way how developers think in general and get them into C# 's dynamic capabilities more deeply. And in turn, how C# continues to evolve in that field. In my opinion, at the current stage of the C# development, the interface concept integration is still deeply derived from strict, very static OOP thinking. This is simply no more. Things are very dynamic and actually the .NET family as a whole is more and more going that direction too. So, just an idea for interfaces to go along the 'dynamic evolution' of languages in general. But if you just miss the ability to invoke that function as it is defined in the interface (even if it doesn't mean it has to conceptionally), because you used to know it like that, technically there is nothing that would prevent a call like: (car as ILoggable)[WriteLog]();
// instead
foreach (var method in (car as ILoggable).GetType().GetMethods()
.Where(m => m.GetCustomAttributes(typeof(WriteLog), true).Length > 0 && m.GetParameters().Count() == 0)
method.Invoke(car, null);
thanks for the link, some interesting stuff there. |
Beta Was this translation helpful? Give feedback.
-
Then why not name the method in the interface |
Beta Was this translation helpful? Give feedback.
-
That sounds a lot like something that could be achieved with a diagnostic analyzer. You would have to use existing syntax, but I don't think that would be an issue. Why do you think this approach is not suitable and it has to be done by the compiler, with special syntax? Also, keep in mind that C# is definitely not going to add features just to support one 3rd party AOP framework. You make it sound like this feature would be generally useful, but I'm not convinced it is. |
Beta Was this translation helpful? Give feedback.
-
sorry for my lack of knowledge, but I don't see anything mentioned about AOP in this wiki article about C#. https://en.wikipedia.org/wiki/C_Sharp_%28programming_language%29 anyway I took a quick look at below article, it sounds cool, you may want to try it. |
Beta Was this translation helpful? Give feedback.
-
are you serious asking this? that has nothing to do with dynamic modularity in complex scenarios. when a class implements class Car : ILoggable
{
public string Name { get; set; }
public string ILoggable.LogName
{
get { return string.Format("Car.{0}", Name); }
}
public void ILoggable.WriteLog(string msg)
{
// Do Some Stuff
}
public void Move(int meters)
{
WriteLog("start");
// Do Some Stuff
WriteLog("end");
}
public void Save()
{
// Do Some Stuff
}
public void Delete()
{
WriteLog("start");
// Do Some Stuff
WriteLog("end");
}
} This is very painful in terms of DRY. a module knows what to do as much as possible. this is primary school coding |
Beta Was this translation helpful? Give feedback.
-
then an attribute could be used somehow to do rest of work for you. |
Beta Was this translation helpful? Give feedback.
-
@MkazemAkhgary thanks for the links. this feature request is not about AOP at all. |
Beta Was this translation helpful? Give feedback.
-
No, that is not the core concept of interfaces. They very specifically are a contract to the consumer of the interface that the advertised members exist. That's it. They don't care how the members are implemented and they have nothing to do with reflection or attributes. @svick is right, if your goal is to find a mechanism through which to enforce that members of a type are decorated with some attribute based on some arbitrary rules then the appropriate solution is to write an analyzer, which is already possible. |
Beta Was this translation helpful? Give feedback.
-
@svick again, this issue has nothing to do with AOP directly. Just came across it by doing AOP. I don't judge whether an interface paradigm such that will be useful in general for sure. Because than attributes would become signatures of interfaces as well, which they are actually, to wich I can rely on in the architecture already also. Not in the implementation, as it is now the case. @HaloFour |
Beta Was this translation helpful? Give feedback.
-
I've seen this approach before. It comes to no good. This proposal is dead in the water unless the personal comments get lost and we can see a use case that interfaces can't handle and attributes can. |
Beta Was this translation helpful? Give feedback.
-
@jnm2 then why continue the cause Behaviour? |
Beta Was this translation helpful? Give feedback.
-
Because I'm an incurable optimist who thinks that calling out bad behavior when I see it and hoping for resolution is better than choosing to ignore the whole conversation. |
Beta Was this translation helpful? Give feedback.
-
That would be a breaking change, so it's not going to happen for the existing If you're designing a new serializer and are worried about this, you could use marker interface instead of marker attribute (or an interface & attribute combination, since that's the only one where this proposal would be useful). In both cases, if your serializer has a requirement that's not expressible in the type system (like |
Beta Was this translation helpful? Give feedback.
-
are you guys for real, or is this a playground for Microsoft's new AI chatbot program |
Beta Was this translation helpful? Give feedback.
-
The attacks are all coming from you, my friend. This is the least effective strategy if you have something to offer. |
Beta Was this translation helpful? Give feedback.
-
@jnm2 no attacks man, in now way. just reflecting he has brought the subject of the issue down to the serializer implementation itself. nevertheless, the link he provided is at least useful in showing that Microsoft is actually aware of the lack of such a feature in the language it self. and btw. Im offering nothing nor I'm selling you something. just a proposal from dev to dev, from my perspective at least. not expecting anything for it. |
Beta Was this translation helpful? Give feedback.
-
Then maybe you aren't seeing it from the outside perspective. This is a personal insult: "are you guys for real, or is this a playground for Microsoft's new AI chatbot program" and it fits anyone's definition of verbal attack.
Let me rephrase: This is the least effective strategy if you have something to propose, from dev to dev. Their ask is simple. Would you please show us how this proposal allows us to do something we couldn't do before? Or show us how it relieves existing pain on a large enough scale to warrant the added language and runtime maintenance, and the mental complexity imposed on ordinary language users? It's not an inherently good thing to have two ways to do the same thing. It's an inherently bad thing. So far we can't see how this is not just another way to do what interfaces already do. Show us. |
Beta Was this translation helpful? Give feedback.
-
I showed 2 examples at least, where current interfaces cant handle them. now, lets try it this way. to keep the most simple case, show me a way to handle the
|
Beta Was this translation helpful? Give feedback.
-
Ok, so the point is to guarantee the existence of members with a specific attribute whose signature fits a specific pattern, in order to be able to invoke the member. So again, it is fundamental to define how that works when in situations the language doesn't currently support, such as multiple matches. Otherwise the feature seems useless compared with interfaces as they already exist, which already cover single match cases. |
Beta Was this translation helpful? Give feedback.
-
I still don't get the point of this. It sounds like you're trying to have interfaces without naming the members, then putting a name in some attribute. We already have a feature in the C# language today which allows you to name the members of interfaces. It works the same for interfaces, classes, structs, and will almost certainly also work the same way for shapes as well. It's a well-cited saying around here that every feature proposal starts with negative 100 'points', and it's up to the proposal to bring it to 100 'points' of value. So far, I see absolutely no use case for mucking around with interfaces in this manner. Please:
So far, all I can see in this thread is a very up-in-the-air idea, and vitriol. Cut the latter, and make the former more concrete. As it stands now, I cannot imagine anyone from the language design team wanting to champion this. |
Beta Was this translation helpful? Give feedback.
-
public class Foo : ISerializable { ... }
public class Bar : Foo { ... } Is |
Beta Was this translation helpful? Give feedback.
-
Without thinking so much about it but reading through briefly why you need to change the language when we can have something like this?
So maybe like @HaloFour pointed out it would be be possible to do that through source generators. |
Beta Was this translation helpful? Give feedback.
-
if but, also this complexity which at the moment takes place in the implementation, whether the given instance is declaring the interface ISerializable
requires explicit [ISerializable] //-> telling the most outer Type has to declare it.
{}
interface ISerializable
requires [ISerializable] //-> the instance will be serialized down the ladder where the attribute was placed
{} the decision is made by the architect in design process, not the coder in implementing the serializer.
fail. power of attributes
So basically you are pointing out that this proposal would be a kik butt feature on Java. As it will keep the benefit of solving this issue by the usage of attributes AND now would be bringing the architectural benefit of using Interfaces for this kind of scenarios as Java engineers did.
fail, once more.
?! interfaces are composed of declarations, nothing else and are compiler enforced.
the weirdness.. constantly bashing and trashing based on non sense. endless loop one might have a look at what this all implies in the actual implementation in the very ordinary and so easy to understand case of the serializer. code / complexity regarding the in respect to the proposed issue, just proceed as follows:
my part here is to raise the fundamental question, which proposes a feature in the language.
|
Beta Was this translation helpful? Give feedback.
-
No. Two methods with the same name and parameters, but different attributes, have the same signature. Therefore attributes are not signatures. That was easy. Oh and you have something else very wrong too: coders design; compilers implement. This misunderstanding on your part seems to have sent you down a rabbit hole over attributes. Time to stop digging and climb on out.
You might want to have a read of #52. As of C# 8, interfaces will never be the same again... |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Having an AOP approach for a specific task, I thought of having a feature in C#, which would allow me already in the architectural design to assert that a type implementing a specific interface contains a member that matches the signature by attribute and member type only without knowing the actual name of the member.
given a simple example:
without such a feature, checks whether a member with the expected attribute exists can be done on runtime, hence no compile time errors.
as mentioned, I came across this idea in designing an AOP approach module implementation. But I think it would be in general definitely a nice feature fitting just great into the already very advanced dynamic feature set of C# targeting 'intelligent' modularity of applications.
Beta Was this translation helpful? Give feedback.
All reactions