泛型传参调用问题

aminic 2011-07-28 08:18:40

//如有一方法签名为:
public virtual void DoSomthing<TLeftEntity, TRigthEntity>();
//那么直接调用时为:
DoSomthing<Person, Address>();
//Person,Address都为已经定义好的类型

//我想把Person,Address以类型的方法传入方法来调用DoSomthing:
ShowData(typeof(Person),typeof(Address));

///方法实现:
public void ShowData(Type t1,Type t2)
{
DoSomthing<t1, t2>();//这样调用是不行的
}


以什么样的方法才能实现对DoSomthing类似上面简述的调用?
...全文
224 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
我姓区不姓区 2011-07-28
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 aminic 的回复:]
我不这么认为,我认为这是由于静态语言的原因造成的,既然C#有反射的方式来解决问题,那就用之,解决问题占首位,相对代码也会比较清爽些。
[/Quote]
用反射性能上的损耗我们暂且不提,代码怎么会变得清爽呢?
cjh200102 2011-07-28
  • 打赏
  • 举报
回复
楼上很全面,不多补充了。

顶一下
odp_denden 2011-07-28
  • 打赏
  • 举报
回复
一楼说得很详细.
aminic 2011-07-28
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 ojlovecd 的回复:]

引用 3 楼 aminic 的回复:

看了看资料,貌似编译期是要指定泛型指定类型的。。。

你说的没错,泛型必须是编译时就指定泛型类型了,要实现你这个目的,必须用反射,而采用反射的话就必然会失去强类型的特性。
其实像你所说的这个效果,论坛经常有人提问,而事实上这是滥用泛型的一种典型例子。
[/Quote]

我不这么认为,我认为这是由于静态语言的原因造成的,既然C#有反射的方式来解决问题,那就用之,解决问题占首位,相对代码也会比较清爽些。
xuexiaodong2009 2011-07-28
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 ojlovecd 的回复:]

引用 3 楼 aminic 的回复:

看了看资料,貌似编译期是要指定泛型指定类型的。。。

你说的没错,泛型必须是编译时就指定泛型类型了,要实现你这个目的,必须用反射,而采用反射的话就必然会失去强类型的特性。
其实像你所说的这个效果,论坛经常有人提问,而事实上这是滥用泛型的一种典型例子。
[/Quote]事实上这是滥用泛型的一种典型例子。
我姓区不姓区 2011-07-28
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 aminic 的回复:]

看了看资料,貌似编译期是要指定泛型指定类型的。。。
[/Quote]
你说的没错,泛型必须是编译时就指定泛型类型了,要实现你这个目的,必须用反射,而采用反射的话就必然会失去强类型的特性。
其实像你所说的这个效果,论坛经常有人提问,而事实上这是滥用泛型的一种典型例子。
showjim 2011-07-28
  • 打赏
  • 举报
回复
//如有一方法签名为:
public virtual void DoSomthing<TLeftEntity, TRigthEntity>();
//那么直接调用时为:
DoSomthing<Person, Address>();
//Person,Address都为已经定义好的类型

//我想把Person,Address以类型的方法传入方法来调用DoSomthing:
ShowData<Person, Address>();

///方法实现:
public void ShowData<TLeftEntity, TRigthEntity>()
{
DoSomthing<TLeftEntity, TRigthEntity>();
}
wangruiyingdemama 2011-07-28
  • 打赏
  • 举报
回复
感觉 c++里也是这样的 java貌似也有 原来c#也有啊
zjq8888882009 2011-07-28
  • 打赏
  • 举报
回复
学习,学习
aminic 2011-07-28
  • 打赏
  • 举报
回复
我的意思是重用DoSomthing,因为有很多类似这样的调用,那么我就只写一个DoSomthing,然后运行时动态传类型参数。这样的话就只能用反射来尝试做了,因为泛型在编译期是需要指定具体类型。而在编译期,我的类型是不确定的。
isjoe 2011-07-28
  • 打赏
  • 举报
回复
[Quote=引用楼主 aminic 的回复:]
///方法实现:
public void ShowData(Type t1,Type t2)
{
DoSomthing<t1, t2>();//这样调用是不行的
}
[/Quote]

你只传递类型对象,而没有实例对象。。能做什么呢?
ruanwei1987 2011-07-28
  • 打赏
  • 举报
回复

//如有一方法签名为:
public void DoSomthing<person, address>()
{ }
//那么直接调用时为:

//Person,Address都为已经定义好的类型

//我想把Person,Address以类型的方法传入方法来调用DoSomthing:


///方法实现:
public void ShowData()
{
DoSomthing<person, address>();//这样调用是不行的
}

class person
{

}
class address
{ }



这样就行了 为什么要那样呢
aminic 2011-07-28
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 sdl2005lyx 的回复:]

楼上说得很细,很好,楼主看看MSDN,或其他相关资料,一般都有例子。。。。。
[/Quote]

只有反射来搞了,写代码时需要指定具体的类型的
sdl2005lyx 2011-07-28
  • 打赏
  • 举报
回复
楼上说得很细,很好,楼主看看MSDN,或其他相关资料,一般都有例子。。。。。
aminic 2011-07-28
  • 打赏
  • 举报
回复
看了看资料,貌似编译期是要指定泛型指定类型的。。。
心灵彩虹 2011-07-28
  • 打赏
  • 举报
回复

泛型方法:


除了定义泛型类之外,还可以定义泛型方法。在泛型方法中,泛型类型用方法声明来定义。
Swap<T>方法把T定义为泛型类型,用于两个参数和一个变量temp:
void Swap<T>(ref T x, ref T y)
{
T temp;
temp = x;
x = y;
y = temp;
}
把泛型类型赋予方法调用,就可以调用泛型方法:
int i = 4;
int j = 5;
Swap<int>(ref i, ref j);
但是,因为C#编译器会通过调用Swap方法来获取参数的类型,所以不需要把泛型类型赋予方法调用。泛型方法可以像非泛型方法那样调用:
int i = 4;
int j = 5;
Swap(ref i, ref j);


心灵彩虹 2011-07-28
  • 打赏
  • 举报
回复

泛型方法

在C#2.0中,方法可以定义特定于其执行范围的泛型参数,如下所示:

public class MyClass<T>
{
//指定MyMethod方法用以执行类型为X的参数
public void MyMethod<X>(X x)
{
//
}

//此方法也可不指定方法参数
public void MyMethod<X>()
{
//
}
} 即使包含类不适用泛型参数,你也可以定义方法特定的泛型参数,如下所示:

public class MyClass
{
//指定MyMethod方法用以执行类型为X的参数
public void MyMethod<X>(X x)
{
//
}

//此方法也可不指定方法参数
public void MyMethod<X>()
{
//
}
} 注意:属性和索引器不能指定自己的泛型参数,它们只能使用所属类中定义的泛型参数进行操作。
在调用泛型方法的时候,你可以提供要在调用场所使用的类型,如下所示:
//调用泛型方法
MyClass myClass = new MyClass();
myClass.MyMethod<int>(3); 泛型推理:在调用泛型方法时,C#编译器足够聪明,基于传入的参数类型来推断出正确的类型,并且它允许完全省略类型规范,如下所示:
//泛型推理机制调用泛型方法
MyClass myClass = new MyClass();
myClass.MyMethod(3); 注意:泛型方法无法只根据返回值的类型推断出类型,代码如下:
public GenericMethodDemo()
{
MyClass myClass = new MyClass();
/****************************************************
无法从用法中推理出方法“GenericMethodDemo.MyClass.MyMethod<T>()”的类型参数。
请尝试显式指定类型参数。
***************************************************/
int number = myClass.MyMethod();
}

public class MyClass
{
public T MyMethod<T>()
{
//
}
} 泛型方法中泛型参数的约束,如下:
public class MyClass
{

public void MyMethod<X>(X x) where X:IComparable<X>
{
//
}
}
您无法为类级别的泛型参数提供方法级别的约束。类级别泛型参数的所有约束都必须在类作用范围中定义,代码如下所示
public class MyClass<T>
{

public void MyMethod<X>(X x,T t) where X:IComparable<X> where T:IComparer<T>
{
//
}
}而下面的代码是正确的
public class MyClass<T> where T:IComparable<T>
{

public void MyMethod<X>(X x,T t) where X:IComparable<X>
{
//
}
} 泛型参数虚方法的重写:子类方法必须重新定义该方法特定的泛型参数,代码如下
public class MyBaseClass
{
public virtual void SomeMethod<T>(T t)
{
//
}
}
public class MyClass :MyBaseClass
{
public override void SomeMethod<X>(X x)
{

}
}同时子类中的泛型方法不能重复基类泛型方法的约束,这一点和泛型类中的虚方法重写是有区别的,代码如下
public class MyBaseClass
{
public virtual void SomeMethod<T>(T t) where T:new()
{
//
}
}
public class MyClass :MyBaseClass
{
//正确写法
public override void SomeMethod<X>(X x)
{

}

////错误 重写和显式接口实现方法的约束是从基方法继承的,因此不能直接指定这些约束
//public override void SomeMethod<X>(X x) where X:new()
//{

//}
} 子类方法调用虚拟方法的基类实现:它必须指定要代替泛型基础方法类型所使用的类型实参。你可以自己显式的指定它,也可以依靠类型推理(如果可能的话)代码如下:
public class MyBaseClass
{
public virtual void SomeMethod<T>(T t) where T:new()
{
//
}
}
public class MyClass :MyBaseClass
{
//正确写法
public override void SomeMethod<X>(X x)
{
base.SomeMethod<X>(x);
base.SomeMethod(x);
}
}泛型委托
在某个类中定义的委托可以使用该类的泛型参数,代码如下
public class MyClass<T>
{
public delegate void GenericDelegate(T t);
public void SomeMethod(T t)
{

}
}
public GenericMethodDemo()
{
MyClass<int> obj = new MyClass<int>();
MyClass<int>.GenericDelegate del;
del = new MyClass<int>.GenericDelegate(obj.SomeMethod);
del(3);
} 委托推理:C#2.0使你可以将方法引用的直接分配转变为委托变量。将上面的代码改造如下
public class MyClass<T>
{
public delegate void GenericDelegate(T t);
public void SomeMethod(T t)
{

}
}
public GenericMethodDemo()
{
MyClass<int> obj = new MyClass<int>();
MyClass<int>.GenericDelegate del;

//委托推理
del = obj.SomeMethod;
del(3);
} 泛型委托的约束:委托级别的约束只在声明委托变量和实例化委托时使用,类似于在类型和方法的作用范围中实施的其他任何约束。
泛型和反射
在Net2.0当中,扩展了反射以支持泛型参数。类型Type现在可以表示带有特定类型的实参(或绑定类型)或未指定类型的泛型(或称未绑定类型)。像C#1.1中那样,您可以通过使用typeof运算符或通过调用每个类型支持的GetType()来获得任何类型的Type。代码如下:
LinkedList<int> list = new LinkedList<int>();
Type type1 = typeof(LinkedList<int>);
Type type2 = list.GetType();
Response.Write(type1 == type2); typeof和GetType()也可以对泛型参数进行操作,如下
public class MyClass<T>
{
public void SomeMethod(T t)
{
Type type = typeof(T);
HttpContext.Current.Response.Write(type==t.GetType());
}
} typeof还可以对未绑定的泛型进行操作,代码如下
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Type unboundType = typeof(MyClass<>);
Response.Write(unboundType.ToString());
}
}

public class MyClass<T>
{
public void SomeMethod(T t)
{
Type type = typeof(T);
HttpContext.Current.Response.Write(type==t.GetType());
}
} 请注意"<>"的用法。要对带有多个类型参数的未绑定泛型类进行操作,请在"<>"中使用","
aminic 2011-07-28
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 ojlovecd 的回复:]

引用 15 楼 aminic 的回复:
我不这么认为,我认为这是由于静态语言的原因造成的,既然C#有反射的方式来解决问题,那就用之,解决问题占首位,相对代码也会比较清爽些。

用反射性能上的损耗我们暂且不提,代码怎么会变得清爽呢?
[/Quote]

不是在所有的地方用反射,只是在系统初始化时调用。性能上损耗也只是微乎其微。
以这样的方式进行就是为了重用,代码量少了,不是相对清爽么?

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧