C# 返回未知的通用列表<;T>;
谢谢你的帮助 如何从方法返回未知的泛型.List类型C# 返回未知的通用列表<;T>;,c#,generics,types,C#,Generics,Types,谢谢你的帮助 如何从方法返回未知的泛型.List类型 public void Main() { List<A> a= GetData("A"); } public List<T> GetData(string listType) { if(listType == "A") { List<A> a= new List<A>() ... return a; } else {
public void Main()
{
List<A> a= GetData("A");
}
public List<T> GetData(string listType)
{
if(listType == "A")
{
List<A> a= new List<A>()
...
return a;
}
else
{
List<B> b = new List<B>()
return b;
}
}
public void Main()
{
列表a=获取数据(“a”);
}
公共列表GetData(字符串listType)
{
如果(列表类型=“A”)
{
列表a=新列表()
...
返回a;
}
其他的
{
列表b=新列表()
返回b;
}
}
在下面的示例中,我收到一个类似的错误:无法将List
转换为List
这可能吗?“返回a;”时出错代码行。此外,我需要做什么来确保线路上不会发生错误:
List<A> a= GetData("A");
List a=GetData(“a”);
谢谢,
史蒂文使用
IList
而不是列表
根据猎户座的回答编辑下面的内容,添加了安托尼琼斯建议的约束
您可能应该有一个A和B继承自的接口/抽象类
public interface IMyInterface { }
public class A : IMyInterface { }
public class B : IMyInterface { }
public List<IMyInterface> GetData<T>() where T : IMyInterface
{
List<IMyInterface> myList = new List<IMyInterface>();
if (typeof(T) == typeof(A))
{
myList.Add(new A());
}
if (typeof(T) == typeof(B))
{
myList.Add(new B());
}
return myList;
}
公共接口IMyInterface{}
公共A类:IMyInterface{}
公共类B:IMyInterface{}
public List GetData(),其中T:IMyInterface
{
List myList=新列表();
如果(类型(T)=类型(A))
{
添加(新的A());
}
如果(类型(T)=类型(B))
{
添加(新的B());
}
返回myList;
}
您不能像这样直接返回列表
为什么??基本上是因为<代码>列出了关于这类事情的更多信息
因此,您必须返回两种类型派生的内容(它们的“共同点”)
同样,您可以返回IList
,(注意非泛型,因此它只是对象的一个列表,或者简单地将其作为对象返回。不幸的是,没有办法保留列表的类型。如果在运行时之前不知道所需的类型,那么泛型可能是该作业的错误工具
如果您的函数根据一个参数显著更改了行为(如更改返回类型),那么它可能应该是两个函数
public void Main() {
List<A> a = GetDataA();
}
public List<A> GetDataA() {
List<A> a= new List<A>()
...
return a;
}
public List<B> GetDataB() {
List<B> b= new List<B>()
...
return b;
}
看起来这个函数不应该是泛型的,实际上应该是两个函数
public void Main() {
List<A> a = GetDataA();
}
public List<A> GetDataA() {
List<A> a= new List<A>()
...
return a;
}
public List<B> GetDataB() {
List<B> b= new List<B>()
...
return b;
}
public void Main(){
列表a=GetDataA();
}
公共列表GetDataA(){
列表a=新列表()
...
返回a;
}
公共列表GetDataB(){
列表b=新列表()
...
返回b;
}
除了返回对象列表之外,另一种选择是确保a和B派生自公共基类型或实现公共接口,然后返回该基类型或接口的列表。在泛型方法上包含一个约束:-
List<ICommon> GetData<T>() where T: ICommon
{
}
List GetData(),其中T:ICommon
{
}
除非有特定原因导致您无法提前指定实际类型,否则您可以将方法本身设置为泛型:
public void Main() {
List<A> a = GetData<A>();
}
public List<TType> GetData<TType>() {
List<TType> list= new List<TType>();
...
return list;
}
public void Main(){
列表a=GetData();
}
公共列表GetData(){
列表=新列表();
...
退货清单;
}
最近,我不得不解决一个类似的问题,提出的解决方案都不令人满意;约束类型参数是不实际的。相反,我让方法的使用者决定如何使用数据。例如,您可以编写String.Split()的通用版本,该版本返回强类型列表,只要您告诉它如何将子字符串转换为T
一旦您愿意将责任转移到调用堆栈上(并轻松地传递lambda),您就可以任意概括此模式。例如,如果GetData()的方式不同(某些响应显然是这样假设的),那么也可以将该函数提升到调用方的作用域中
演示:
static void Main(字符串[]args)
{
var parseMe=“你好,世界!1,2,3,死牛肉”;
//不需要编写完全通用的Process()方法来解析字符串——您可以
//将拆分和转换组合为一种方法,并消除2/3的类型参数
列出句子=parseMe.Split(“!”,str=>str);
列表编号=句子[1]。拆分(“,”,str=>Int32.Parse(str,NumberStyles.allowhexsspecifier | NumberStyles.allowreadingwhite));
//更有趣一点的
var lettersPerSentence=过程(句子,
sList=>从sList中的s选择s.ToCharArray(),
chars=>chars.Count(c=>Char.IsLetter(c));
}
静态列表拆分(此字符串str、字符分隔符、Func Convert)
{
返回进程(str,s=>s.Split(分隔符),Convert.ToList();
}
静态IEnumerable进程(TInput输入、Func GetData、Func转换)
{
从GetData中的基准返回(输入)
选择转换(基准);
}
函数编程大师可能会对这个探索产生哈欠:“你只是在做地图几次。”甚至C++的人也可能会声称这是一个例子,其中模板技术(即STL转换(+)+函子)比泛型需要更少的工作。但是作为一个主要从事C语言工作的人,很高兴找到一个既保留了类型安全性又保留了惯用语言用法的解决方案。
我知道它的方式太晚了,但我来到这里时遇到了同样的问题,这就是我如何使用接口解决的。我想我会为了其他人的利益发布它
public interface IEntity
{
int ID
{
get;
set;
}
}
public class Entity2:IEntity
{
public string Property2;
public int ID
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
}
对于Entity1也是如此
现在在我的课堂上(我的业务层),我有了这个方法
public List<IEntity> GetEntities(Common.EntityType entityType)
{
List<IEntity> entities = new List<IEntity>();
switch (entityType)
{
case Common.EntityType.Accounts:
Entity1 entity1 = new Entity1();
entity1.Property1 = "AA";
entities.Add(entity1);
break;
case Common.EntityType.Brands:
Entity2 entity2 = new Entity2();
entity2.Property2 = "AA";
entities.Add(entity2);
break;
default:
break;
}
return entities;
}
公共列表GetEntities(Common.EntityType EntityType)
{
列表实体=新列表();
开关(实体类型)
{
case Common.EntityType.Accounts:
Entity1 Entity1=新的Entity1();
实体1.Property1=“AA”;
实体。添加(实体1);
打破
case Common.EntityType.Brands:
Entity2 Entity2=新的Entity2();
entity2.Property2=“AA”;
BusinessClass b = new BusinessClass();
List<IEntity> a = b.GetEntities(Common.EntityType.Accounts);
/// <summary>
/// The Client
/// </summary>
interface IDataContainer
{
void AcceptDataProcessor(IDataProcessor dataProcessor);
}
/// <summary>
/// The Visitor.
/// </summary>
interface IDataProcessor
{
void WorkOn<TData>(List<TData> data);
}
class DataContainer<TData> : IDataContainer
{
readonly List<TData> list;
public DataContainer(List<TData> list)
{
this.list = list;
}
public void AcceptDataProcessor(IDataProcessor dataProcessor)
{
dataProcessor.WorkOn(list); // Here the type is known.
}
}
class PrintDataProcessor : IDataProcessor
{
public void WorkOn<TData>(List<TData> data)
{
// print typed data.
}
}
public void Main()
{
var aContainer = GetData("A");
var bContainer = GetData("B");
var printProccessor = new PrintDataProcessor();
aContainer.AcceptDataProcessor(printProccessor); // Will print A data
bContainer.AcceptDataProcessor(printProccessor); // Will print B data
}
public IDataContainer GetData(string listType)
{
if (listType == "A")
return new DataContainer<A>(new List<A>());
if (listType == "B")
return new DataContainer<B>(new List<B>());
throw new InvalidOperationException();
}