C # 'daki bu belirgin öz referansın amacı nedir?


21

Projelerimden birinde kullanım için Piranha ( http://piranhacms.org/ ) adlı açık kaynaklı bir CMS'yi değerlendiriyorum . En azından benim için aşağıdaki kodu ilginç ve biraz kafa karıştırıcı buldum. Bazıları sınıfın neden aynı tip bir temelden devraldığını anlamama yardımcı olabilir mi?

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; }
}

Bir sınıf BasePage<T>tanımlanıyorsa, neden neden miras Page<T> where T: BasePage<T>? Hangi özel amaca hizmet ediyor?



7
Olumsuz oylara ve yakın oylara rağmen, bunda topluluk bunu yanlış anladı. Bu, bu sitenin ne hakkında olduğuna dair özünde, özel ve önemsiz bir tasarım kararıyla ilgili açıkça belirtilmiş bir sorudur.
Robert Harvey

Sadece takıl ve kapatılınca tekrar aç.
David Arno

F sınırlı polimorfizm kavramı üzerine okuyun :)
Eyvind

1
@Eyvind Aslında yaptım. F Sınırlı polimorfizm hakkında okumak isteyenler için, işte link staff.ustc.edu.cn/~xyfeng/teaching/FOPL/lectureNotes/…
Xami Yen

Yanıtlar:


13

Bazıları sınıfın neden aynı tip bir temelden devraldığını anlamama yardımcı olabilir mi?

O devralan oluyor, değil Page<T>, ama Tkendisinden türetilen bir türü tarafından parametrelenmelidir sınırlandırılmış olmasından BasePage<T>.

Nedenini anlamak için, type parametresinin Tgerçekte nasıl kullanıldığına bakmanız gerekir . Bir miktar kazdıktan sonra, miras zincirini yükseltirken, bu sınıfa girersiniz:

( 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);
    }
}

Görebildiğim kadarıyla, genel kısıtlamanın tek amacı, Createyöntemin mümkün olan en az soyut türü döndürmesini sağlamaktır.

Buna değip değmeyeceğinden emin değilim, ama belki de arkasında iyi bir sebep var, ya da sadece kolaylık sağlamak için olabilir, ya da arkasında çok fazla madde yoktur ve bu alçıdan kaçınmak için çok ayrıntılı bir yöntemdir (BTW, I Ben burada demek değil, sadece insanların bunu yaptığını söylüyorum).

Bunun, yansımayı engellemelerine izin vermediğini unutmayın - bu api.Pages, typeof(T).Nameonu elde typeIdeden ve contentService.Createyöntemi olarak ileten sayfaların deposudur ( buraya bakın ).


5

Bunun yaygın bir kullanımı, kendi kendine kullanılan kavramlarla ilgilidir: mevcut tip için çözülen bir tür parametresi. Bir arayüz ile bir clone()yöntem tanımlamak istediğinizi varsayalım . clone()Yöntem her zaman çağrıldığı sınıfının bir örneğini dönmelidir. Bu yöntemi nasıl ilan edersiniz? Kendi kendine tipleri olan bir jenerik sistemde bu kolaydır. Sadece döndüğünü söyledin self. Bu yüzden benim bir sınıfım varsa Foo, klon yönteminin geri döndüğü bildirilmelidir Foo. Java'da ve (bir cursory search'den) C #, bu bir seçenek değil. Bunun yerine, bu sınıfta gördükleriniz gibi beyanlar görüyorsunuz. Bunun bir kişisel tiple aynı şey olmadığını ve sağladığı kısıtlamaların zayıf olduğunu anlamak önemlidir. Her ikisinden de türetilen Foobir Barsınıfınız varsaBasePage, (yanılmıyorsam) tarafından parametrelenecek Foo'yu tanımlayabilirsiniz Bar. Bu faydalı olabilir, ancak bence tipik olarak, çoğu zaman, bunun kendi tipi gibi kullanılacağı ve etrafta dolaşıp başka türlerle yer değiştirmenize rağmen, yapmanız gereken bir şey olmadığı anlaşılıyor. Uzun zaman önce bu fikirle oynamıştım, ancak Java jeneriklerinin kısıtlamaları nedeniyle bu çabaya değmeyeceği sonucuna vardım. C # jenerikler elbette daha tam özellikli ama bu aynı sınırlamaya sahip görünüyor.

Bu yaklaşımın kullandığı bir başka zaman, ağaçlar veya diğer özyinelemeli yapılar gibi grafiğe benzer türler oluşturduğunuzda ortaya çıkar. Bu bildirim, türlerin Sayfa gereksinimlerini karşılamasına izin verir, ancak türü daha da ayrıntılandırır. Bunu bir ağaç yapısında görebilirsiniz. Örneğin , uygulamaların, yalnızca herhangi bir Düğüm türü içeren Ağaçlar değil, belirli bir Düğüm alt türü (genellikle kendi türleri.) Olduğunu tanımlamasına izin vermek için Nodeparametrelendirilebilir Node. Sanırım burada olanlardan daha fazlası var.


3

Gerçekte kodu yazan kişi olarak Filip'in doğru olduğunu ve kendi kendini referans alan genel öğenin aslında temel sınıfta yazılı bir Create yöntemi sağlama kolaylığı olduğunu söyleyebilirim.

Bahsettiği gibi, hala çok fazla yansıma var ve sonunda sayfa türünü çözmek için yalnızca türün adı kullanılıyor. Bunun nedeni dinamik modelleri de yükleyebilmenizdir, yani modeli ilk oluşturan CLR türüne erişmeden gerçekleştirebilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.