我在设计界面时遇到问题
我有这些接口:
interface IField {
}
interface IScreenField : IField {
}
interface ITable {
CustomCollection<IField> CustomCollection { get; set; }
}
interface IScreen
{
AnotherCustomCollection<IScreenField> AnotherCustomCollection { get; set; }
}
IScreen
接口应继承自ITable
,但显示错误,我必须实现IField
的集合,但我已经实现了IScreenField
解决方案是什么?
我上传了一个示例项目以进一步说明问题
您可以在Screen
类中查看错误消息:
Screen
未实现接口成员ITable.Fields
。 Screen.Fields
无法实现ITable.Fields
,因为它没有匹配的返回类型CusomCollection<IField>
以下是示例: Sample project
答案 0 :(得分:0)
此示例的描述可帮助您解决问题:如果IExample2继承了另一个Interface,则在实现IExample2时需要实现 接口+ IExample2中继承的接口的方法中声明的所有方法(属性等...)。请记住,实现接口时,必须实现该接口的所有成员(甚至必须实现链中所有接口的成员),并且所有返回类型在接口和类中必须相同。 / p>
interface IExample
{
void Method1();
}
interface IExample2 : IExample
{
void Method2();
}
class Screen : IExample2
{
public void Method2()
{
}
public void Method1()
{
}
}
链示例
interface IExample
{
void Method1();
}
interface IExample2 : IExample
{
void Method2();
}
interface IExample3 : IExample2
{
void Method3();
}
答案 1 :(得分:0)
您可以执行以下操作:
public class Screen : IScreen
{
public string Name { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public AnotherCustomCollection<IBaseField> Fields { get; set; }
CustomCollection<IField> ITable.Fields
{
get
{
throw new System.NotSupportedException();
}
}
}
显然,编译器喜欢这种方式,如果您执行以下操作:
public static void Main(string[] args)
{
var collection = new List<IScreen>()
{
new Screen
{
Fields = new AnotherCustomCollection<ScreenInterface.IBaseField>
{
new TextField()
{
Name = "Hello"
}
}
}
};
var y = collection.First();
//Prints "Hello"
Console.WriteLine(string.Join(" ", y.Fields.Select(x => x.Name)));
Console.ReadLine();
}
但是,如果您正在使用上层界面(ITable)
public static void Main(string[] args)
{
var collection = new List<ITable>() //here
{
new Screen
{
Fields = new AnotherCustomCollection<ScreenInterface.IBaseField>
{
new TextField()
{
Name = "Hello"
}
}
}
};
var y = collection.First();
//Throws NotSupportedException
Console.WriteLine(string.Join(" ", y.Fields.Select(x => x.Name)));
Console.ReadLine();
}
我的猜测是没有泛型继承的概念,如果将AnotherCustomCollection
的条件泛型参数从IBaseField
切换为IField
可以证明这一点。如果引发异常,请返回Fields
上的公共Screen.ITable.Fields
属性。编译器将自动识别具体属性,并且一切正常。
因此,要使其正常工作,请定义隐式运算符或自定义getter:
public class Screen : IScreen
{
public string Name { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public AnotherCustomCollection<IBaseField> Fields { get; set; }
CustomCollection<IField> ITable.Fields
{
get
{
var customCollection = new CustomCollection<IField>();
customCollection.AddRange(Fields);
return customCollection;
}
}
}
答案 2 :(得分:0)
这是我在之前的帖子中发布的答案。由于您之前的问题在我无法解决之前已被搁置 提交答案。
不查看完整代码很难识别问题,但是基于您所说的,我相信您已经明确实现了IScreenField
,并且编译器无法找到{{1 }}。
结帐以下以获取更多信息: https://www.codeproject.com/Articles/1000374/Explicit-Interface-VS-Implicit-Interface-in-Csharp
更新:查看代码后
首先,您需要了解接口的隐式和显式实现之间的区别:
隐式::您可以访问界面属性和属性,就好像它们是类的一部分一样。 显式::您只能在将类视为已实现的接口时访问属性和属性。
IField
类的问题在于它实现了Screen
接口,而该接口又实现了IScreen
接口。这两个接口都有一个名为ITable
的属性。
因此,问题浮出水面,您需要
明确地实现Fields
类中的Fields
属性。
注意:与您使用不同的返回类型无关。由于您在两个接口中都实现了Screen
属性,因此假设从每个接口访问该属性时,您期望的值是不同的。
Fields
现在如何访问它们?要访问每个接口的public class Screen : IScreen
{
public string Name { get; set; }
AnotherCustomCollection<IBaseField> IScreen.Fields
{
get
{
return default(AnotherCustomCollection<IBaseField>);
}
}
CustomCollection<IField> ITable.Fields
{
get
{
return default(CustomCollection<IField>);
}
}
public string Title { get; set; }
public string Description { get; set; }
}
属性,您需要访问Fields
对象 as 。
例如:
Screen
var screen = new Screen();
var fields = screen.Fields; // Error
var fields = (screen as IScreen).Fields; // returns property value of IScreen Fields
以下是完整的代码: https://dotnetfiddle.net/5KS0Xd
希望这很有帮助。祝一切顺利,愉快。