繁体   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