Define a class as a universal implementation. Why / how does it work?

I usually created Prism events used by EventAggregator, for example:

public class SomeEvent : CompositePresentationEvent<SomeEventArgs> { }

 public class SomeEventArgs { public string Name { get; set; } } 

But, looking at the code of my colleagues, I noticed what they did:

 public class SomeEvent : CompositePresentationEvent<SomeEvent> { public string Name { get; set; } } 

I think my first question is - why is this even compiling? It seems to me that it implements a class that is not yet defined. Secondly, does this negatively affect the application in general, is it insignificant or better?

+6
source share
1 answer

I guess my first question is why does it even compile?

What rule in the specification do you consider to be your violation?

It seems to me that it implements a class that is not yet defined.

I think you will need to indicate the exact meaning of each of these terms so that the statement is considered accurate or not. The compiler knows about CompositePresentationEvent since it is declared elsewhere (presumably), and it knows about SomeEvent because this class is declared. It looks like a field of type Foo inside the class Foo is completely valid.

It is also very useful to be able to do this - especially for comparison. For instance:

 public sealed class Foo : IComparable<Foo> 

says that any instance of the Foo class knows how to compare itself with another instance, so it can be used for sorting in a safe way. In the case of structures, this also reduces boxing, since calling x.CompareTo(y) will not need boxing when x , as you know, is of the type that IComparable<> implements IComparable<> .

Note that types can get much more interesting and dimly recursive. Take this (slightly modified) example from my protocol buffer port :

 public interface IMessage<TMessage, TBuilder> where TMessage : IMessage<TMessage, TBuilder> where TBuilder : IBuilder<TMessage, TBuilder> public interface IBuilder<TMessage, TBuilder> where TMessage : IMessage<TMessage, TBuilder> where TBuilder : IBuilder<TMessage, TBuilder> 

The goal here is basically to get two types - β€œmessage” and β€œbuilder” so that you can always build each other. For instance:

 public class Foo : IMessage<Foo, FooBuilder> { ... } public class FooBuilder : IBuilder<Foo, FooBuilder> { ... } 
+8
source

Source: https://habr.com/ru/post/916391/


All Articles