【发布时间】:2022-12-12 19:45:43
【问题描述】:
我有以下场景,涉及如下几个接口
internal interface ITranslation
{
string LanguageCode { get; set; }
string Title { get; set; }
}
任何包含翻译的对象都将实现 ITranslation 接口。其中一些对象也可以有同义词,所以我有另一个接口
internal interface ITranslationWithSynonmys : ITranslation
{
IList<string> Synonyms { get; set; }
}
下一步我已经为任何有翻译并且可以翻译成不同语言的对象定义了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; }
}
ITranslation 和 ITranslationWithSynonmys 的具体实现是
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> 的对象的服务,我将其定义为
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:参数 1:无法从“TestInheritance.TranslatableWithSynonymsEntity”转换为“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; }
}
有没有办法避免这种情况?还是我采取了错误的方法?
谢谢
【问题讨论】:
-
看起来你可以完全放弃泛型——不清楚你在这里需要它们做什么?
-
我需要泛型,因为 ITranslatable 可以有一个 ITranslation 列表或任何继承自 ITranslation 的接口。我不希望它总是返回 ITranslatable。正如您在 TranslatableWithSynonymsEntity 的情况下看到的那样,它返回 IList<ITranslationWithSynonmys>
-
现在,由于您的 ITranslatableWithSynonyms 和 ITranslatable 接口指定了一些
IList<T> Something {get;set;}属性,因此不可能使它们协变。因此,您要么必须找到一种方法来避免使用 setter 和一些非协变 interface<T> 类型作为属性的返回类型(不允许使接口协变)的属性,要么您必须找到一个不同的类/界面设计完全... -
@MySkullCaveIsADarkPlace 基于stackoverflow.com/questions/5832094/covariance-and-ilist,一种选择是使用 IReadOnlyList<out T> 代替 IList<T>。也许我可以适应
标签: c# generics inheritance interface