C# 当泛型类型取决于从何处调用时,为类创建泛型接口
我试图创建一个通用接口,该接口可以由需要能够返回Class1或Class2类型列表的类实现。我一直无法实现这一点,因为我需要传入IRules泛型类型,如果传入ClassAbstract,我会遇到下面的问题,这是一个非常简短的泛型示例,说明了我真正要处理的问题,其中一个属性只是派生类型中的一个,而不是基类型 我不知道如何才能让它以我想要的方式工作,基本上在那一节中,我可以检查列表的类型,然后指定要做什么,但问题是,因为我将ClassAbstract作为泛型参数传递,这也不起作用……有没有一种方法可以让它正常工作而不必指定接口键入,因为我实际上不知道它是一个Class1列表还是一个Class2列表,它是基于从哪里调用的?很明显,我可以复制代码,只对每个类类型使用一次方法,但是代码太多了,我不认为这应该很难做到我想做的事情,但也许我错了C# 当泛型类型取决于从何处调用时,为类创建泛型接口,c#,generics,interface,C#,Generics,Interface,我试图创建一个通用接口,该接口可以由需要能够返回Class1或Class2类型列表的类实现。我一直无法实现这一点,因为我需要传入IRules泛型类型,如果传入ClassAbstract,我会遇到下面的问题,这是一个非常简短的泛型示例,说明了我真正要处理的问题,其中一个属性只是派生类型中的一个,而不是基类型 我不知道如何才能让它以我想要的方式工作,基本上在那一节中,我可以检查列表的类型,然后指定要做什么,但问题是,因为我将ClassAbstract作为泛型参数传递,这也不起作用……有没有一种方法可
public interface IRules<T> {
List<T>GetAdditionalPropRules(List<T> list1);
List<T>SetAdditionalPropRules(List<T> list1);
}
public ClassAbstract {
public string NAME {get;set;}
public string AGE {get;set;}
}
public class Class1: ClassAbstract {
public string JOB {get;set;}
}
public class Class2: ClassAbstract {
}
public class Rules MyProperties: IRules<ClassAbstract>{ **<--- I Want this to be able to accept either Class1 or Class2**
public List<ClassAbstract> SetAdditionalPropRules(List<ClassAbstract> myList) {
foreach(dynamic item in myList) {
if(item.NAME == "Joe") {
myList.Add(new ClassAbstract {
AGE = 30,
JOB = "Tester" **<--- ISSUE RIGHT HERE -- ClassAbstract Does not have property JOB**
}
}
}
}
}
也许,像这样如果您的Class1和Class2基于某个接口:
interface IClassAbsract
{
string Name { get; set; }
string Age { get; set; }
}
public class Class1: IClassAbsract
{
public string Name { get; set; }
public string Age { get; set; }
}
public class Class2 : IClassAbsract
{
public string Name { get; set; }
public string Age { get; set; }
}
public class ListRule
{
public List<IClassAbsract> List { get; set; } = new List<IClassAbsract>();
}
然后,以后,可以这样使用:
...
...
//populate list with testing instances
var list = new ListRule();
var c1 = new Class1() { Name = "Class #1", Age = "11" };
list.List.Add(c1);
var c2 = new Class2() { Name = "Class #2", Age = "22" };
list.List.Add(c2);
...
//then, get only certain types, and populate second list "myList": for example, pull only of type Class1:
public void Test2(List<IClassAbsract> list)
{
if (list == null || !list.Any())
{
throw new System.ArgumentNullException("empty");
}
//pull only of type Class1:
List<IClassAbsract> myList = new List<IClassAbsract>();
myList.AddRange(list
.Where(e => e is Class1)
.Select(e => new Class1() { Age = e.Age, Name = "Joe" })
.ToList()
);
}
这对你有帮助吗
using System;
using System.Linq;
using System.Collections.Generic;
namespace ConsoleApp
{
static partial class Program
{
输出:
Joe / Class1 : 20 ()
Joe / Class2 : 25
John / Class1 : 30 ()
John / Class2 : 35
Joe / Class1 : 30 (Tester)
Joe / Class2 : 25
John / Class1 : 30 ()
John / Class2 : 35
你把泛型和动态混合在一起了。它们代表着完全相反的概念。我强烈建议您不要使用这种解决方案。在这里,您可以添加一个新的类1。因为Class1和Class2都继承ClassAbstract,所以它们都是ClassAbstract。与您的问题无关,但是在foreach循环中用var代替dynamic更为正确。您的问题不清楚。您试图编写的方法在列表上运行。不清楚为什么每个叫乔的人都一定是测试人员。也就是说,如果您想设置JOB属性,并且该属性只存在于Class1类中,那么当然需要创建Class1的新实例。那么,为什么不这样做呢?为什么要使用新的ClassAbstract而不是新的Class1?请改进您的问题,使其有意义。如果作业属性接收到Class1,您似乎希望设置AdditionalProjectRules来设置作业属性。如果是2级,你想做什么?如果它应该做一些不同的事情,它不是通用的。泛型方法适用于对各种类型执行相同操作,在这种情况下,您希望根据类型执行不同操作。不起作用…无法通过引用转换、装箱转换、取消装箱转换、换行转换或空类型转换将类型“System.Collections.generic.List”转换为“Class1”。我将放弃这种方式…可能不是一个好主意,我只是讨厌复制这么多代码,因为实际上只有两行。它必须工作。答案更新为完整的文件代码和测试。我使用了您的代码,但您应该重构它,并将RulesMyProperties类设置为静态,因为它似乎是一个助手。
static void Test()
{
var rules = new RulesMyProperties();
var list = new List<ClassAbstract>();
list.Add(new Class1 { NAME = "Joe", AGE = 20 });
list.Add(new Class2 { NAME = "Joe", AGE = 25 });
list.Add(new Class1 { NAME = "John", AGE = 30 });
list.Add(new Class2 { NAME = "John", AGE = 35 });
Action print = () =>
{
foreach ( var item in list )
{
Console.Write($"{item.NAME} / {item.GetType().Name} : {item.AGE}");
if ( item is Class1 )
Console.Write($" ({((Class1)item).JOB})");
Console.WriteLine();
}
};
print();
rules.SetAdditionalPropRules(list);
Console.WriteLine();
print();
}
}
public class RulesMyProperties : IRules<ClassAbstract>
{
public List<ClassAbstract> SetAdditionalPropRules(List<ClassAbstract> myList)
{
foreach ( var item in myList.ToList() )
{
if ( item != null )
if ( item.NAME == "Joe" )
{
if ( item is Class1 )
{
( item as Class1 ).AGE = 30;
( item as Class1 ).JOB = "Tester";
}
else
{
myList.Remove(item);
myList.Add(new Class1
{
NAME = "Joe",
AGE = 30,
JOB = "Tester"
});
}
break;
}
}
return myList;
}
public List<ClassAbstract> GetAdditionalPropRules(List<ClassAbstract> list1)
{
throw new NotImplementedException();
}
}
public interface IRules<T>
{
List<T> GetAdditionalPropRules(List<T> list1);
List<T> SetAdditionalPropRules(List<T> list1);
}
public class ClassAbstract
{
public string NAME { get; set; }
public int AGE { get; set; }
}
public class Class1 : ClassAbstract
{
public string JOB { get; set; }
}
public class Class2 : ClassAbstract
{
}
}
Joe / Class1 : 20 ()
Joe / Class2 : 25
John / Class1 : 30 ()
John / Class2 : 35
Joe / Class1 : 30 (Tester)
Joe / Class2 : 25
John / Class1 : 30 ()
John / Class2 : 35