gpt4 book ai didi

C#继承接口(interface)列表

转载 作者:太空宇宙 更新时间:2023-11-03 22:35:52 24 4
gpt4 key购买 nike

我对 C# 接口(interface)有点陌生,遇到了一个相当尴尬的解决继承接口(interface)列表问题的扩展方法的方法。示例界面如下所示:

public interface IData
{
int Value { get; set; }
}

public interface IDataWithName : IData
{
string Name { get; set; }
}

public interface IDataContainer
{
IList<IData> DataList { get; set; }
}

public interface IDataWithNameContainer : IDataContainer
{
new IList<IDataWithName> DataList { get; set; }
}

使用扩展方法:

public static class ExtensionMethod
{
public static int CountNumberOfIDataItems(this IDataContainer i)
{
return i.DataList.Count();
}
}

实现这些接口(interface)时,IList DataList和IList IDataContainer.DataList都需要实现。虽然这是可能的,但生成的代码并不优雅:

public class DataNameImplimentatioFixed : IDataWithNameContainer
{
public IList<IDataWithName> DataList { get; set; }
IList<IData> IDataContainer.DataList
{
get => new List<IData>(DataList);
set
{
DataList = new List<IDataWithName>();
foreach (IDataWithName _dataLoop in value) { DataList.Add(_dataLoop); }
}
}
}

每次调用扩展时都复制列表可能会导致一些性能问题,并且需要额外检查以确保 IDataContainer 上的任何其他方法不会尝试添加继承自 IData 而不是 IDataWithName 的类。

感觉应该有更好的方法来使用扩展方法,它不会像 future 的扩展那样容易受到问题的影响。我能想到的最佳解决方案是将 IList DataList 从 IDataContainer 中取出,并为包含列表的每个类提供单独的扩展方法。

谁能想出比这更好的解决方案?

最佳答案

问题是 IDataWithNameContainer 隐藏了它从 IDataContainer 继承的 DataList 属性,而不是扩展方法。它不应该这样做。

创建仅接受特定 IData 实现的派生容器类的简单方法是使容器接口(interface)通用并在 IDataWithNameContainer 中使用更严格的类型约束:

public interface IData
{
int Value { get; set; }
}

public interface IDataWithName : IData
{
string Name { get; set; }
}

public interface IDataContainer<T> where T:IData
{
IList<T> DataList { get; set; }
}

public interface IDataWithNameContainer<T> : IDataContainer<T> where T:IDataWithName
{

}

public static class ExtensionMethod
{
public static int CountNumberOfIDataItems<T>(this IDataContainer<T> i) where T:IData
{
return i.DataList.Count;
}
}

以这种方式创建命名容器很容易:

public class Boo:IDataWithName 
{
public int Value { get; set; }
public string Name { get; set; }
}


public class BooContainer: IDataWithNameContainer<Boo>
{
public IList<Boo> DataList { get; set; }
}

更新

顺便说一句,没有理由在循环中将新项目添加到DataListList 构造函数可以接受具有初始值的 IEnumerable:

public class BooContainer: IDataWithNameContainer<Boo>
{
IList<Boo> _list=new List<Boo>();
public IList<Boo> DataList
{
get => _list;
set => _list=new List<Boo>(value);
}
}

这允许通过将列表和数组的内容复制到新列表中来将列表和数组存储到 DataList

如果有人设置为空,这将抛出。为避免这种情况,可以在 setter 中使用 null 替换运算符:

    set => _list=new List<Boo>(value ?? new Boo[0]); 

关于C#继承接口(interface)列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55181578/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com