.NET Self Reference

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
8
down vote

favorite












I am evaluating an open source CMS called Piranha (http://piranhacms.org/) for use in one of my projects. I found the following code interesting and a bit confusing, at least to me. Can some help me understand why the class is inheriting from a base of same type?



public abstract class BasePage<T> : Page<T> where T : BasePage<T>

/// <summary>
/// Gets/sets the page heading.
/// </summary>
[Region(SortOrder = 0)]
public Regions.PageHeading Heading get; set;



If a class of BasePage<T> is being defined, why inherit from Page<T> where T: BasePage<T>? What specific purpose does it serve?










share|improve this question

















  • 5




    blogs.msdn.microsoft.com/ericlippert/2011/02/03/…
    – David Arno
    4 hours ago






  • 4




    Despite the downvotes and close votes, I think the community got it wrong on this one. This is a clearly-stated question having to do with a specific and non-trivial design decision, the very essence of what this site is about.
    – Robert Harvey
    4 hours ago






  • 1




    @RobertHarvey: could not agree more, but I guess we will not be able to educate persons like gnat on this ;-) And he is obviously not the only one who mistakenly believes any question with some code in it need to be closed.
    – Doc Brown
    3 hours ago











  • Just hang around and reopen it when it gets closed.
    – David Arno
    3 hours ago














up vote
8
down vote

favorite












I am evaluating an open source CMS called Piranha (http://piranhacms.org/) for use in one of my projects. I found the following code interesting and a bit confusing, at least to me. Can some help me understand why the class is inheriting from a base of same type?



public abstract class BasePage<T> : Page<T> where T : BasePage<T>

/// <summary>
/// Gets/sets the page heading.
/// </summary>
[Region(SortOrder = 0)]
public Regions.PageHeading Heading get; set;



If a class of BasePage<T> is being defined, why inherit from Page<T> where T: BasePage<T>? What specific purpose does it serve?










share|improve this question

















  • 5




    blogs.msdn.microsoft.com/ericlippert/2011/02/03/…
    – David Arno
    4 hours ago






  • 4




    Despite the downvotes and close votes, I think the community got it wrong on this one. This is a clearly-stated question having to do with a specific and non-trivial design decision, the very essence of what this site is about.
    – Robert Harvey
    4 hours ago






  • 1




    @RobertHarvey: could not agree more, but I guess we will not be able to educate persons like gnat on this ;-) And he is obviously not the only one who mistakenly believes any question with some code in it need to be closed.
    – Doc Brown
    3 hours ago











  • Just hang around and reopen it when it gets closed.
    – David Arno
    3 hours ago












up vote
8
down vote

favorite









up vote
8
down vote

favorite











I am evaluating an open source CMS called Piranha (http://piranhacms.org/) for use in one of my projects. I found the following code interesting and a bit confusing, at least to me. Can some help me understand why the class is inheriting from a base of same type?



public abstract class BasePage<T> : Page<T> where T : BasePage<T>

/// <summary>
/// Gets/sets the page heading.
/// </summary>
[Region(SortOrder = 0)]
public Regions.PageHeading Heading get; set;



If a class of BasePage<T> is being defined, why inherit from Page<T> where T: BasePage<T>? What specific purpose does it serve?










share|improve this question













I am evaluating an open source CMS called Piranha (http://piranhacms.org/) for use in one of my projects. I found the following code interesting and a bit confusing, at least to me. Can some help me understand why the class is inheriting from a base of same type?



public abstract class BasePage<T> : Page<T> where T : BasePage<T>

/// <summary>
/// Gets/sets the page heading.
/// </summary>
[Region(SortOrder = 0)]
public Regions.PageHeading Heading get; set;



If a class of BasePage<T> is being defined, why inherit from Page<T> where T: BasePage<T>? What specific purpose does it serve?







c# architecture .net cms






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 5 hours ago









Xami Yen

573




573







  • 5




    blogs.msdn.microsoft.com/ericlippert/2011/02/03/…
    – David Arno
    4 hours ago






  • 4




    Despite the downvotes and close votes, I think the community got it wrong on this one. This is a clearly-stated question having to do with a specific and non-trivial design decision, the very essence of what this site is about.
    – Robert Harvey
    4 hours ago






  • 1




    @RobertHarvey: could not agree more, but I guess we will not be able to educate persons like gnat on this ;-) And he is obviously not the only one who mistakenly believes any question with some code in it need to be closed.
    – Doc Brown
    3 hours ago











  • Just hang around and reopen it when it gets closed.
    – David Arno
    3 hours ago












  • 5




    blogs.msdn.microsoft.com/ericlippert/2011/02/03/…
    – David Arno
    4 hours ago






  • 4




    Despite the downvotes and close votes, I think the community got it wrong on this one. This is a clearly-stated question having to do with a specific and non-trivial design decision, the very essence of what this site is about.
    – Robert Harvey
    4 hours ago






  • 1




    @RobertHarvey: could not agree more, but I guess we will not be able to educate persons like gnat on this ;-) And he is obviously not the only one who mistakenly believes any question with some code in it need to be closed.
    – Doc Brown
    3 hours ago











  • Just hang around and reopen it when it gets closed.
    – David Arno
    3 hours ago







5




5




blogs.msdn.microsoft.com/ericlippert/2011/02/03/…
– David Arno
4 hours ago




blogs.msdn.microsoft.com/ericlippert/2011/02/03/…
– David Arno
4 hours ago




4




4




Despite the downvotes and close votes, I think the community got it wrong on this one. This is a clearly-stated question having to do with a specific and non-trivial design decision, the very essence of what this site is about.
– Robert Harvey
4 hours ago




Despite the downvotes and close votes, I think the community got it wrong on this one. This is a clearly-stated question having to do with a specific and non-trivial design decision, the very essence of what this site is about.
– Robert Harvey
4 hours ago




1




1




@RobertHarvey: could not agree more, but I guess we will not be able to educate persons like gnat on this ;-) And he is obviously not the only one who mistakenly believes any question with some code in it need to be closed.
– Doc Brown
3 hours ago





@RobertHarvey: could not agree more, but I guess we will not be able to educate persons like gnat on this ;-) And he is obviously not the only one who mistakenly believes any question with some code in it need to be closed.
– Doc Brown
3 hours ago













Just hang around and reopen it when it gets closed.
– David Arno
3 hours ago




Just hang around and reopen it when it gets closed.
– David Arno
3 hours ago










2 Answers
2






active

oldest

votes

















up vote
5
down vote



accepted











Can some help me understand why the class is inheriting from a base of same type?




It's not, it's inheriting from Page<T>, but T itself is constrained to be parameterized by a type that is derived from BasePage<T>.



To infer why, you have to look at how the type parameter T is actually used.
After some digging, as you move up the inheritance chain, you'll come up upon this class:



(github)



public class GenericPage<T> : PageBase where T : GenericPage<T>

public bool IsStartPage
get return !ParentId.HasValue && SortOrder == 0;


public GenericPage() : base()

public static T Create(IApi api, string typeId = null)

return api.Pages.Create<T>(typeId);




As far as I can see, the only purpose for the generic constraint is to make sure that the Create method returns the least abstract type possible.



Not sure if it's worth it, though, but perhaps there's some good reason behind it, or it could be only for convenience, or maybe there's no too much substance behind it and it's just an overly elaborate way to avoid a cast (BTW, I'm not implying that is the case here, I'm just saying that people do that sometimes).



Note that this doesn't allow them to avoid reflection - the api.Pages is a repository of pages that obtains typeof(T).Name, and passes it as the typeId to the contentService.Create method (see here).






share|improve this answer



























    up vote
    0
    down vote













    One common use of this is related to the concept of self-types: a type parameter that resolves to the current type. Let's say you want to define an interface with a clone() method. The clone() method must always return an instance of the class on which it was called. How do you declare that method? In a generics system that has self-types, it's easy. You just say it returns self. So if I have a class Foo, the clone method must be declared to return Foo. In Java and (from a cursory search) C#, this isn't an option. You instead see declarations like what you see in this class. It's important to understand that this is not the same thing as a self-type and the restrictions it provides are weaker. If you have a Foo and a Bar class that both derive from BasePage, you can (if I am not mistaken) define Foo to be parameterized by Bar. That might be useful but I think typically, most of the time, this will be used like a self-type and it's just understood that even though you can goof around and substitute with other types, it's not something you should do. I played around with this idea long ago but came to the conclusion that it wasn't worth the effort because the limitations of Java generics. C# generics are of course more fully featured but it seems to have this same limitation.



    The other time this approach get's used it when you are building graph-like types such as trees or other recursive structures. The declaration allows types to meet the requirements of Page but further refine the type. You might see this in a tree structure. For example a Node might be parameterized by Node to allow for implementations to define that they aren't just Trees containing any type of Node but a specific sub-type of Node (usually their own type.) I think that's more of what's going on here.






    share|improve this answer




















      Your Answer








      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "131"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













       

      draft saved


      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f380874%2fnet-self-reference%23new-answer', 'question_page');

      );

      Post as a guest






























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      5
      down vote



      accepted











      Can some help me understand why the class is inheriting from a base of same type?




      It's not, it's inheriting from Page<T>, but T itself is constrained to be parameterized by a type that is derived from BasePage<T>.



      To infer why, you have to look at how the type parameter T is actually used.
      After some digging, as you move up the inheritance chain, you'll come up upon this class:



      (github)



      public class GenericPage<T> : PageBase where T : GenericPage<T>

      public bool IsStartPage
      get return !ParentId.HasValue && SortOrder == 0;


      public GenericPage() : base()

      public static T Create(IApi api, string typeId = null)

      return api.Pages.Create<T>(typeId);




      As far as I can see, the only purpose for the generic constraint is to make sure that the Create method returns the least abstract type possible.



      Not sure if it's worth it, though, but perhaps there's some good reason behind it, or it could be only for convenience, or maybe there's no too much substance behind it and it's just an overly elaborate way to avoid a cast (BTW, I'm not implying that is the case here, I'm just saying that people do that sometimes).



      Note that this doesn't allow them to avoid reflection - the api.Pages is a repository of pages that obtains typeof(T).Name, and passes it as the typeId to the contentService.Create method (see here).






      share|improve this answer
























        up vote
        5
        down vote



        accepted











        Can some help me understand why the class is inheriting from a base of same type?




        It's not, it's inheriting from Page<T>, but T itself is constrained to be parameterized by a type that is derived from BasePage<T>.



        To infer why, you have to look at how the type parameter T is actually used.
        After some digging, as you move up the inheritance chain, you'll come up upon this class:



        (github)



        public class GenericPage<T> : PageBase where T : GenericPage<T>

        public bool IsStartPage
        get return !ParentId.HasValue && SortOrder == 0;


        public GenericPage() : base()

        public static T Create(IApi api, string typeId = null)

        return api.Pages.Create<T>(typeId);




        As far as I can see, the only purpose for the generic constraint is to make sure that the Create method returns the least abstract type possible.



        Not sure if it's worth it, though, but perhaps there's some good reason behind it, or it could be only for convenience, or maybe there's no too much substance behind it and it's just an overly elaborate way to avoid a cast (BTW, I'm not implying that is the case here, I'm just saying that people do that sometimes).



        Note that this doesn't allow them to avoid reflection - the api.Pages is a repository of pages that obtains typeof(T).Name, and passes it as the typeId to the contentService.Create method (see here).






        share|improve this answer






















          up vote
          5
          down vote



          accepted







          up vote
          5
          down vote



          accepted







          Can some help me understand why the class is inheriting from a base of same type?




          It's not, it's inheriting from Page<T>, but T itself is constrained to be parameterized by a type that is derived from BasePage<T>.



          To infer why, you have to look at how the type parameter T is actually used.
          After some digging, as you move up the inheritance chain, you'll come up upon this class:



          (github)



          public class GenericPage<T> : PageBase where T : GenericPage<T>

          public bool IsStartPage
          get return !ParentId.HasValue && SortOrder == 0;


          public GenericPage() : base()

          public static T Create(IApi api, string typeId = null)

          return api.Pages.Create<T>(typeId);




          As far as I can see, the only purpose for the generic constraint is to make sure that the Create method returns the least abstract type possible.



          Not sure if it's worth it, though, but perhaps there's some good reason behind it, or it could be only for convenience, or maybe there's no too much substance behind it and it's just an overly elaborate way to avoid a cast (BTW, I'm not implying that is the case here, I'm just saying that people do that sometimes).



          Note that this doesn't allow them to avoid reflection - the api.Pages is a repository of pages that obtains typeof(T).Name, and passes it as the typeId to the contentService.Create method (see here).






          share|improve this answer













          Can some help me understand why the class is inheriting from a base of same type?




          It's not, it's inheriting from Page<T>, but T itself is constrained to be parameterized by a type that is derived from BasePage<T>.



          To infer why, you have to look at how the type parameter T is actually used.
          After some digging, as you move up the inheritance chain, you'll come up upon this class:



          (github)



          public class GenericPage<T> : PageBase where T : GenericPage<T>

          public bool IsStartPage
          get return !ParentId.HasValue && SortOrder == 0;


          public GenericPage() : base()

          public static T Create(IApi api, string typeId = null)

          return api.Pages.Create<T>(typeId);




          As far as I can see, the only purpose for the generic constraint is to make sure that the Create method returns the least abstract type possible.



          Not sure if it's worth it, though, but perhaps there's some good reason behind it, or it could be only for convenience, or maybe there's no too much substance behind it and it's just an overly elaborate way to avoid a cast (BTW, I'm not implying that is the case here, I'm just saying that people do that sometimes).



          Note that this doesn't allow them to avoid reflection - the api.Pages is a repository of pages that obtains typeof(T).Name, and passes it as the typeId to the contentService.Create method (see here).







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered 3 hours ago









          Filip Milovanović

          1,16318




          1,16318






















              up vote
              0
              down vote













              One common use of this is related to the concept of self-types: a type parameter that resolves to the current type. Let's say you want to define an interface with a clone() method. The clone() method must always return an instance of the class on which it was called. How do you declare that method? In a generics system that has self-types, it's easy. You just say it returns self. So if I have a class Foo, the clone method must be declared to return Foo. In Java and (from a cursory search) C#, this isn't an option. You instead see declarations like what you see in this class. It's important to understand that this is not the same thing as a self-type and the restrictions it provides are weaker. If you have a Foo and a Bar class that both derive from BasePage, you can (if I am not mistaken) define Foo to be parameterized by Bar. That might be useful but I think typically, most of the time, this will be used like a self-type and it's just understood that even though you can goof around and substitute with other types, it's not something you should do. I played around with this idea long ago but came to the conclusion that it wasn't worth the effort because the limitations of Java generics. C# generics are of course more fully featured but it seems to have this same limitation.



              The other time this approach get's used it when you are building graph-like types such as trees or other recursive structures. The declaration allows types to meet the requirements of Page but further refine the type. You might see this in a tree structure. For example a Node might be parameterized by Node to allow for implementations to define that they aren't just Trees containing any type of Node but a specific sub-type of Node (usually their own type.) I think that's more of what's going on here.






              share|improve this answer
























                up vote
                0
                down vote













                One common use of this is related to the concept of self-types: a type parameter that resolves to the current type. Let's say you want to define an interface with a clone() method. The clone() method must always return an instance of the class on which it was called. How do you declare that method? In a generics system that has self-types, it's easy. You just say it returns self. So if I have a class Foo, the clone method must be declared to return Foo. In Java and (from a cursory search) C#, this isn't an option. You instead see declarations like what you see in this class. It's important to understand that this is not the same thing as a self-type and the restrictions it provides are weaker. If you have a Foo and a Bar class that both derive from BasePage, you can (if I am not mistaken) define Foo to be parameterized by Bar. That might be useful but I think typically, most of the time, this will be used like a self-type and it's just understood that even though you can goof around and substitute with other types, it's not something you should do. I played around with this idea long ago but came to the conclusion that it wasn't worth the effort because the limitations of Java generics. C# generics are of course more fully featured but it seems to have this same limitation.



                The other time this approach get's used it when you are building graph-like types such as trees or other recursive structures. The declaration allows types to meet the requirements of Page but further refine the type. You might see this in a tree structure. For example a Node might be parameterized by Node to allow for implementations to define that they aren't just Trees containing any type of Node but a specific sub-type of Node (usually their own type.) I think that's more of what's going on here.






                share|improve this answer






















                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  One common use of this is related to the concept of self-types: a type parameter that resolves to the current type. Let's say you want to define an interface with a clone() method. The clone() method must always return an instance of the class on which it was called. How do you declare that method? In a generics system that has self-types, it's easy. You just say it returns self. So if I have a class Foo, the clone method must be declared to return Foo. In Java and (from a cursory search) C#, this isn't an option. You instead see declarations like what you see in this class. It's important to understand that this is not the same thing as a self-type and the restrictions it provides are weaker. If you have a Foo and a Bar class that both derive from BasePage, you can (if I am not mistaken) define Foo to be parameterized by Bar. That might be useful but I think typically, most of the time, this will be used like a self-type and it's just understood that even though you can goof around and substitute with other types, it's not something you should do. I played around with this idea long ago but came to the conclusion that it wasn't worth the effort because the limitations of Java generics. C# generics are of course more fully featured but it seems to have this same limitation.



                  The other time this approach get's used it when you are building graph-like types such as trees or other recursive structures. The declaration allows types to meet the requirements of Page but further refine the type. You might see this in a tree structure. For example a Node might be parameterized by Node to allow for implementations to define that they aren't just Trees containing any type of Node but a specific sub-type of Node (usually their own type.) I think that's more of what's going on here.






                  share|improve this answer












                  One common use of this is related to the concept of self-types: a type parameter that resolves to the current type. Let's say you want to define an interface with a clone() method. The clone() method must always return an instance of the class on which it was called. How do you declare that method? In a generics system that has self-types, it's easy. You just say it returns self. So if I have a class Foo, the clone method must be declared to return Foo. In Java and (from a cursory search) C#, this isn't an option. You instead see declarations like what you see in this class. It's important to understand that this is not the same thing as a self-type and the restrictions it provides are weaker. If you have a Foo and a Bar class that both derive from BasePage, you can (if I am not mistaken) define Foo to be parameterized by Bar. That might be useful but I think typically, most of the time, this will be used like a self-type and it's just understood that even though you can goof around and substitute with other types, it's not something you should do. I played around with this idea long ago but came to the conclusion that it wasn't worth the effort because the limitations of Java generics. C# generics are of course more fully featured but it seems to have this same limitation.



                  The other time this approach get's used it when you are building graph-like types such as trees or other recursive structures. The declaration allows types to meet the requirements of Page but further refine the type. You might see this in a tree structure. For example a Node might be parameterized by Node to allow for implementations to define that they aren't just Trees containing any type of Node but a specific sub-type of Node (usually their own type.) I think that's more of what's going on here.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered 2 hours ago









                  JimmyJames

                  12.1k1947




                  12.1k1947



























                       

                      draft saved


                      draft discarded















































                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f380874%2fnet-self-reference%23new-answer', 'question_page');

                      );

                      Post as a guest













































































                      Comments

                      Popular posts from this blog

                      What does second last employer means? [closed]

                      Installing NextGIS Connect into QGIS 3?

                      One-line joke