C# 将泛型类型强制转换为子类
我从泛型类型开始,我一直坚持我的项目。也许我不太懂泛型。解释已插入内联。基本上我需要实现C# 将泛型类型强制转换为子类,c#,generics,C#,Generics,我从泛型类型开始,我一直坚持我的项目。也许我不太懂泛型。解释已插入内联。基本上我需要实现Do()方法,但我不知道如何解决: 公共抽象类MyGenericClass{} 公共类MyGenericClass:MyGenericClass { 公开表达; 公共MyGenericClass(表达式) { 这个表达式=表达式; } } 公共类MyClass { //我需要保存一个泛型类的列表,以便以后使用。 //我现在不知道T2。 //所以我选择使用继承作为解决方法(MyGenericClass和MyGe
Do()
方法,但我不知道如何解决
:
公共抽象类MyGenericClass{}
公共类MyGenericClass:MyGenericClass
{
公开表达;
公共MyGenericClass(表达式)
{
这个表达式=表达式;
}
}
公共类MyClass
{
//我需要保存一个泛型类的列表,以便以后使用。
//我现在不知道T2。
//所以我选择使用继承作为解决方法(MyGenericClass和MyGenericClass)。
//也许这不是个好办法,但我找不到其他办法。
公共列表MyGenericList=新列表();
//我在这里接收参数参数T2作为表达式的一部分。
//我在列表中保留了这个表达式。
公共MyGenericClass接收方法(表达式)
{
MyGenericClass GenericMP=新的MyGenericClass(表达式);
添加(genericmp);
返回genericmp;
}
}
公共类客户端
{
我的班级1;
//class1已创建,其字段MyGenericList已填充。
//然后当我调用Do()。。。。
公营部门
{
foreach(class1.MyGenericList中的变量项)
{
//我需要这样的东西,
//但它没有编译,因为我不知道这里的T2。
//Do()方法的调用方不知道T2。
MyGenericClass myGenericItem=(MyGenericClass)项;
var a=myGenericItem.expression;
}
}
}
您必须以某种方式为Do()
提供T2
参数。因此,我的解决方案是创建一个相同类型的方法参数。我还嵌套了这些类型,以确保它们都引用相同的T
我还将参数重命名为更具描述性的参数
// T -> TArg
// T2 -> TResult
public abstract class MyBaseClass<TArg>
{
public class MyExpressionClass<TResult> : MyBaseClass<TArg>
{
public Expression<Func<TArg, TResult>> Expression { get; private set; }
public MyExpressionClass(Expression<Func<TArg, TResult>> expression)
{
this.Expression=expression;
}
}
public class MyCollectionClass
{
public List<MyBaseClass<TArg>> MyGenericList = new List<MyBaseClass<TArg>>();
public MyExpressionClass<TResult> ReceivingMethod<TResult>(Expression<Func<TArg, TResult>> expression)
{
var genericImp = new MyExpressionClass<TResult>(expression);
MyGenericList.Add(genericImp);
return genericImp;
}
}
public class Client
{
public MyCollectionClass List = new MyCollectionClass();
public void Do<TResult>()
{
foreach(var item in List.MyGenericList)
{
var expr = item as MyExpressionClass<TResult>;
if(expr!=null)
{
var a = expr.Expression;
Console.WriteLine(a);
}
}
}
}
}
class Program
{
static void Main(string[] args)
{
var client = new MyBaseClass<int>.Client();
// add conversion expressions
client.List.ReceivingMethod((i) => (i).ToString());
client.List.ReceivingMethod((i) => (2*i).ToString());
client.List.ReceivingMethod((i) => (3*i).ToString());
// The programmer has to manually enforce the `string` type
// below based on the results of the expressions above. There
// is no way to enforce consistency because `TResult` can be
// _any_ type.
client.Do<string>();
// Produces the following output
//
// i => i.ToString()
// i => (2*i).ToString()
// i => (3*i).ToString()
}
}
//T->target
//T2->TResult
公共抽象类MyBaseClass
{
公共类MyExpressionClass:MyBaseClass
{
公共表达式{get;private set;}
公共MyExpressionClass(表达式)
{
这个表达式=表达式;
}
}
公共类MyCollectionClass
{
公共列表MyGenericList=新列表();
公共MyExpressionClass接收方法(表达式)
{
var genericmp=新的MyExpressionClass(表达式);
添加(genericmp);
返回genericmp;
}
}
公共类客户端
{
public MyCollectionClass List=new MyCollectionClass();
公营部门
{
foreach(List.MyGenericList中的变量项)
{
var expr=作为MyExpressionClass的项;
如果(expr!=null)
{
变量a=表达式;
控制台写入线(a);
}
}
}
}
}
班级计划
{
静态void Main(字符串[]参数)
{
var client=new MyBaseClass.client();
//添加转换表达式
client.List.ReceivingMethod((i)=>(i.ToString());
client.List.ReceivingMethod((i)=>(2*i.ToString());
client.List.ReceivingMethod((i)=>(3*i.ToString());
//程序员必须手动执行'string'类型
//下面是基于上述表达式的结果
//无法强制执行一致性,因为'TResult'可以
//任何类型。
client.Do();
//生成以下输出
//
//i=>i.ToString()
//i=>(2*i).ToString()
//i=>(3*i).ToString()
}
}
解决方案1灵感来源于@KMoussa comment。我已使用抽象方法将责任委托给MyGenericClass
。这似乎是一个更好的设计。所有子类都将实现此方法DoTheWork()
。只能使用T
param从我的Client.Do()
方法调用:
public abstract class MyGenericClass<T>
{
public abstract string DoTheWork();
}
public class MyGenericClass<T, T2> : MyGenericClass<T>
{
public override string DoTheWork()
{
// I can use expression here
}
private Expression<Func<T, T2>> expression { get; set; }
public MyGenericClass(Expression<Func<T, T2>> expression)
{
this.expression = expression;
}
}
public class MyClass<T>
{
public List<MyGenericClass<T>> MyGenericList = new List<MyGenericClass<T>>();
public void ReceivingMethod<T2>(Expression<Func<T, T2>> expression)
{
MyGenericClass<T, T2> genericImp = new MyGenericClass<T, T2>(expression);
}
}
public class Client<T>
{
MyClass<T> class1;
public void Do()
{
// I don't need to cast to MyGenericClass<T, T2>
foreach (MyGenericClass<T> myGenericItem in class1.MyGenericList)
{
string result = myGenericItem.DoTheWork();
}
}
}
你考虑过使用而不是吗?此时你必须使用反射。或者真的试着想出一个不同的设计。泛型意味着允许您编写基本上独立于类型的代码,而不允许您将许多不同类型分组在一起。如何使用
Do
myGenericItem?如果它不需要执行任何特定于T2
的操作,那么您可以在MyGenericClass
上定义抽象方法,该方法在派生类中实现,并由do
@Jesus调用。我的意思是,您为什么需要访问表达式?只是为了执行它并得到Func的结果吗?因为如果是这样的话,你可以有一个为t2返回对象的抽象方法,我看到两个危险信号。a) 构建层次结构以处理各种表达式
,而不是直接保留Func
;b)创建基类型列表并尝试强制转换为派生类型。不幸的是,C#
在这方面相当薄弱。另外,我建议嵌套所有需要
的类型,以减少声明量。我无法编译MyExpressionClass…
。我需要添加类型参数TArg
:MyExpressionClass…
进行编译。问题是Do()
的调用方不知道
我的示例中的代码编译率为100%。我在发帖前检查过了。如果你有错误,可能是某个地方的打字错误MyExpression
嵌套在MyBaseClass
中,并从中使用TArg
。是的,编译率为100%。我看不出类是嵌套的。很抱歉
public abstract class MyGenericClass<T>
{
public abstract string DoTheWork();
}
public class MyGenericClass<T, T2> : MyGenericClass<T>
{
public override string DoTheWork()
{
// I can use expression here
}
private Expression<Func<T, T2>> expression { get; set; }
public MyGenericClass(Expression<Func<T, T2>> expression)
{
this.expression = expression;
}
}
public class MyClass<T>
{
public List<MyGenericClass<T>> MyGenericList = new List<MyGenericClass<T>>();
public void ReceivingMethod<T2>(Expression<Func<T, T2>> expression)
{
MyGenericClass<T, T2> genericImp = new MyGenericClass<T, T2>(expression);
}
}
public class Client<T>
{
MyClass<T> class1;
public void Do()
{
// I don't need to cast to MyGenericClass<T, T2>
foreach (MyGenericClass<T> myGenericItem in class1.MyGenericList)
{
string result = myGenericItem.DoTheWork();
}
}
}
public abstract class MyGenericClass<T>
{
public abstract Type type { get; set; }
}
public class MyGenericClass<T, T2> : MyGenericClass<T>
{
public Expression<Func<T, T2>> expression { get; set; }
public MyGenericClass(Expression<Func<T, T2>> expression)
{
type = typeof(T2); // I save the type of T2
this.expression = expression;
}
}
public class MyClass<T>
{
public List<MyGenericClass<T>> MyGenericList = new List<MyGenericClass<T>>();
public void ReceivingMethod<T2>(Expression<Func<T, T2>> expression)
{
MyGenericClass<T, T2> genericImp = new MyGenericClass<T, T2>(expression);
}
}
public class Client<T>
{
MyClass<T> class1;
public void Do()
{
foreach (MyGenericClass<T> myGenericItem in class1.MyGenericList)
{
MethodInfo method = GetType().GetMethod("MethodWithArgument");
MethodInfo generic = method.MakeGenericMethod(new Type[] { myGenericItem.type });
string g = (string)generic.Invoke(this, new object[] { myGenericItem });
}
}
// I introduce T2 in this method
public string MethodWithArgument<T2>(MyGenericClass<T> myClass)
{
// Now, the casting is valid
MyGenericClass<T, T2> mySubClass = (MyGenericClass<T, T2>)myClass;
var a = mySubClass.expression;
// I can work with expression here
}
}