簡體   English   中英

.NET中的通用接口和inheritance

[英]Generic interfaces and inheritance in .NET

我有以下場景,涉及如下幾個接口

    internal interface ITranslation
    {
        string LanguageCode { get; set; }
        string Title { get; set; }
    }

任何保存翻譯的 object 都將實現ITranslation接口。 其中一些對象也可以有同義詞,所以我有另一個接口

    internal interface ITranslationWithSynonmys : ITranslation
    {
        IList<string> Synonyms { get; set; }
    }

下一步,我為任何具有翻譯且可以翻譯成不同語言的 object 定義了ITranslatable<T>接口

    internal interface ITranslatable<T> where T : ITranslation
    {
        IList<T> Translations { get; set; }
    }

而當涉及同義詞時, ITranslatableWithSynonyms<T>看起來像這樣

    internal interface ITranslatableWithSynonyms<T> : ITranslatable<T> where T : ITranslationWithSynonmys
    {
        IList<T> SynonymTanslations { get; set; }
    }

ITranslationITranslationWithSynonmys的具體實現是

    internal class BaseTranslation : ITranslation
    {
        public string Title { get; set; }
        public string LanguageCode { get; set; }
    }

    internal class BaseTranslationWithSynonmys : ITranslationWithSynonmys
    {
        public IList<string> Synonyms { get; set; }
        public string LanguageCode { get; set; }
        public string Title { get; set; }
    }

而可以翻譯的實體將是

    internal class TranslatableEntity : ITranslatable<ITranslation>
    {
        public IList<ITranslation> Translations { get; set; }
    }

如果它有同義詞

    internal class TranslatableWithSynonymsEntity : ITranslatableWithSynonyms<ITranslationWithSynonmys>
    {
        public IList<ITranslationWithSynonmys> SynonymTanslations { get; set; }
        public IList<ITranslationWithSynonmys> Translations { get; set; }
    }

接下來,我正在創建一個可以翻譯任何實現ITranslatable<T>的 object 的服務,我將其定義為

    internal class TranslationService
    {
        internal string Translate(ITranslatable<ITranslation> translatable, string languageCode)
        {
            // It will iterate through the Translations list to find the correct translation
            return string.Empty;
        }
    }

現在,當我嘗試使用該服務時,我正在寫

var translationService = new TranslationService();
var translatableEntity = new TranslatableEntity();
var translatableWithSynonymsEntity = new TranslatableWithSynonymsEntity();
string x = translationService.Translate(translatableEntity, "en");
string y = translationService.Translate(translatableWithSynonymsEntity, "en");

這里最后一行translationService.Translate(translatableWithSynonymsEntity, "en")無法編譯並出現錯誤 CS1503: Argument 1: cannot convert from 'TestInheritance.TranslatableWithSynonymsEntity' to 'TestInheritance.ITranslatable<TestInheritance.ITranslation>'

TranslatableWithSynonymsEntity確實沒有實現ITranslatable<ITranslation> ,但它實現了ITranslatableWithSynonyms<ITranslationWithSynonmys> ,其中ITranslatableWithSynonyms<T>繼承自ITranslatable<T>ITranslationWithSynonmys繼承自ITranslation

我可以通過讓TranslatableWithSynonymsEntity同時實現ITranslatableWithSynonyms<ITranslationWithSynonmys>ITranslatable<ITranslation>來編譯代碼,但這意味着要管理兩個列表並且看起來不干凈

    internal class TranslatableWithSynonymsEntity : ITranslatableWithSynonyms<ITranslationWithSynonmys>, ITranslatable<ITranslation>
    {
        public IList<ITranslationWithSynonmys> SynonymTanslations { get; set; }
        public IList<ITranslationWithSynonmys> Translations { get; set; }
        IList<ITranslation> ITranslatable<ITranslation>.Translations { get; set; }
    }

有沒有辦法避免這種情況? 還是我采取了錯誤的方法?

謝謝

默認情況下,泛型參數是不變的,在方法Translate中,您希望類型為<ITranslation> ,因此您必須提供一個類型,其(或其父代)泛型參數恰好為<ITranslation>

在您的示例中,您不能簡單地將參數標記為協變,因為它包含一個同時具有 getter 和 setter 的屬性。

既然問題是泛型參數,解決問題,不指定一個,其實你已經約束了泛型參數。

interface ITranslatable<T> where T : ITranslation

方法(或類)只需要用相同的約束聲明。

internal string Translate<T>(ITranslatable<T> translatable, string languageCode)
     where T : ITranslation

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM