泛型方法中类型判断的问题

时间:2022-05-08 19:22:53
我想实现这样一个方法:
        public IList<T> GetGroupInfoList<T>(Guid uid)
        {
            IList<T> list = new List<T>();
            如果T是XX类,则SQL语句为=“...”
            如果T是YY类,则SQL语句为=“...”

            执行数据查询
      
            返回的字段填充到object[]中
             T t = new T(object[]) //T的构造函数均是这样的 T(params objcet[] arr)
            list.add(t)
            return list;
        }

就是上面这样的功能,该怎么实现呢?

32 个解决方案

#1


我试着实现,一路碰壁

#2


比如数据表Group中有ID Name Intro Ico字段
我有时只需查询出一组ID Name 形成List<X> 然后交给ObjectDataSource
  Class X中有字段ID Name
有时只需查询出一组ID Intro 形成List<Y> 然后交给ObjectDataSource
  Class Y中有字段ID Intro

#3


if (typeof(T) is XX)
{
}
else if (typeof(T) is YY)
{
}

#4


public IList<T> GetGroupInfoList<T>(Guid uid)
        {
            IList<T> list = new List<T>();
            如果T是XX类,则SQL语句为=“...”
            if(typeof(T)==typeof(XX))
             ...
            如果T是YY类,则SQL语句为=“...”
            if(typeof(T)==typeof(YY))
            ..
            执行数据查询
      
            返回的字段填充到object[]中
             T t = new T(object[]) //T的构造函数均是这样的 T(params objcet[] arr)
            list.add(t)
            return list;
        }

#5


警告:
 if (typeof(T) is XX)  给定表达式始终不是所提供的(“XX”)类型
错误:
T t = new T(object[]) 这里变量类型“T”没有 new() 约束,因此无法创建该类型的实例

#6


我也就是这么做的,不过碰到了上面的问题

#7


不用is,用==typeof(xx)

#8


学习

#9


emp(Thinking) 对的,试了下,警告消失了:)
那二个错误呢?

#10


改成
public IList<T> GetGroupInfoList<T>(Guid uid)
            where T: new()
出现的错误是:   T t = new T(object[])   “T”: 创建变量类型的实例时无法提供参数

#11


帮顶,不清楚,T的构造函数均是这样的 T(params objcet[] arr)
应该可以啊

#12


emp(Thinking)
传入的类型的构造函数均是X(params objcet[] arr) 或 Y(params objcet[] arr)
但是在这个泛型方法里,T当然是未知的,所以是否需要采用另一种方法,如接口或抽象基类

#13


或者有同样能实现这样功能的设计模式可以使用?

#14


MSDN上的解释是这样的
错误消息 
“identifier”:创建变量类型的实例时无法提供参数

如果对类型参数上的 new 运算符的调用带有参数,则会发生此错误。可以使用未知参数类型上的 new 运算符调用的唯一构造函数是不带参数的构造函数。如果需要调用另一个构造函数,请考虑使用类类型约束或接口约束。

但是用接口约束,接口不可以有构造函数的啊,用了类类型约束,还是同样的错误-_-!

#15


最终写出来的东西是这样的:

public IList<T> GetGroupInfoList<T>(Guid uid): where T: myT
        {
            IList<T> list = new List<T>();
            T t = new T(uid) // myT的构造函数均是这样的 myT(Guid uid)
            list.add(t)
            return list;
        }

#16


你把问题搞复杂了,太有才了,所以反而整出了问题。

对于:
            如果T是XX类,则SQL语句为=“...”
            如果T是YY类,则SQL语句为=“...”

            执行数据查询
      
            返回的字段填充到object[]中
的处理应该是各种T从myT继承而来的,各个T在new(guid)构造方法中只需要知道自己的SQL,调用myT中定义的Protected的数据查询方法,把object[]消化在自己类型内部。

面向对象不是大杂烩,多态的关键就是根本上消去对类型的“switch...case...”或者说连续的“if...else if....”结构。你看看各种多态应用,是不是这样的?

这样做了之后,不用在设计一个类型处理流程时把其它类型都杂烩在一起,扩展的时候也不需要重构。而你的原来的那段代码,当T是其它类型时,就必须重构,否则逻辑就彻底乱了——没有考虑所有子类而仅仅考虑了两种子类,所以一看就是用面向对象的语法代码来偷运结构化的设计思想的。

#17


结构化在处理扩展问题是,用一大堆“switch....case....”来判断,甚至入侵入早期的面向对象设计模式中被表述成“控制类型”之类的多余设计。实际上,这些在面向对象方法中,都可以通过比较纯粹、简练的多态结构来解决。“设计模式”是相当繁琐、冗长、八股的一本书。纯粹的面向对象在设计软件时更为简洁方便。

#18


哦,实例化对象可以从类型得到constructor方法然后invoke,包括guid参数。

#19


嗯,又发现我写的那段代码忘记写new约束了。

自己改一下吧。总之是泛型应该当作类型扩展用,不要当作类型聚合用。

#20


先谢谢sp1234(嘿嘿) :)
寝室快熄灯了,明天来看

#21


studing

#22


但是我是在分层设计中这样做的。类型都是Model,而那个方法在DAL中的
该怎么设计呢?

#23


最好是先定义一个基类baseGroup,其中包含带有构造函数含有参数object[]
然后在泛型的约束中where T: baseGroup
再解决你的判断类型的问题

#24


实际上在泛型的方法中包含判断类型这样的做法我觉得不是很妥当的

#25


@sp1234(嘿嘿)
兄弟太有才了,嘿嘿:)

按sp1234所说那样,更好的应该就是XX,YY同时继承于myT,在XX,YY的类中执行SQL语中。无需在进行typeof()判断。
hoho

#26


menuvb(戏子,白日做梦)
那我不是要在object中 参入数据层的东西

#27


1、不要生搬硬套,自己觉得该怎么写就怎么写
2、不要拘泥于形式和理论,所有的一切,都是为了简化代码

#28


Ivony(授人以鱼不如授人以渔,上海谋生) 
分清楚了 有助于系统的更改与扩展

#29


很简单啊,代码如下:
 class TMenu
    {
        public TMenu()
        {
        }
        public string getName()
        {
            return "AAA";
        }
    }
    class menu<T> where T : TMenu, new()

    {
        public T obj;
        public menu()
        {
        }
        public menu(T obj)
        {
            this.obj = obj;
        }
        public string GetStr()
        {
            return obj.getName();
        }
         public string MyCreateObj()
         {
               T KK = new T();//注意这里创建哦.
              return   KK.getName();
         }
    } 

    class Test
    {
       
        static void Main()
        {
            menu<TMenu> MyMenu = new menu<TMenu>(new TMenu());
            System.Console.WriteLine(MyMenu.MyCreateObj());
        }
    }

#30


关键的就是
class menu <T> where T : TMenu,  new() 

#31


to:sp1234
你的实例代码是有问题的,如果你加了new(),最后创建类的实例时会因构造函数不能接受参数而编译不通过。而你要不加new(),就不能实例化。

我怀疑这是C#语言在泛型编程上的一个局限。

#32


我试过了,要么提示:

创建变量类型的实例时无法提供参数

要么提示:

变量类型“W”没有 new() 约束,因此无法创建该类型的实例

总之就是不能在实例化对象时为构造函数提供参数。

#1


我试着实现,一路碰壁

#2


比如数据表Group中有ID Name Intro Ico字段
我有时只需查询出一组ID Name 形成List<X> 然后交给ObjectDataSource
  Class X中有字段ID Name
有时只需查询出一组ID Intro 形成List<Y> 然后交给ObjectDataSource
  Class Y中有字段ID Intro

#3


if (typeof(T) is XX)
{
}
else if (typeof(T) is YY)
{
}

#4


public IList<T> GetGroupInfoList<T>(Guid uid)
        {
            IList<T> list = new List<T>();
            如果T是XX类,则SQL语句为=“...”
            if(typeof(T)==typeof(XX))
             ...
            如果T是YY类,则SQL语句为=“...”
            if(typeof(T)==typeof(YY))
            ..
            执行数据查询
      
            返回的字段填充到object[]中
             T t = new T(object[]) //T的构造函数均是这样的 T(params objcet[] arr)
            list.add(t)
            return list;
        }

#5


警告:
 if (typeof(T) is XX)  给定表达式始终不是所提供的(“XX”)类型
错误:
T t = new T(object[]) 这里变量类型“T”没有 new() 约束,因此无法创建该类型的实例

#6


我也就是这么做的,不过碰到了上面的问题

#7


不用is,用==typeof(xx)

#8


学习

#9


emp(Thinking) 对的,试了下,警告消失了:)
那二个错误呢?

#10


改成
public IList<T> GetGroupInfoList<T>(Guid uid)
            where T: new()
出现的错误是:   T t = new T(object[])   “T”: 创建变量类型的实例时无法提供参数

#11


帮顶,不清楚,T的构造函数均是这样的 T(params objcet[] arr)
应该可以啊

#12


emp(Thinking)
传入的类型的构造函数均是X(params objcet[] arr) 或 Y(params objcet[] arr)
但是在这个泛型方法里,T当然是未知的,所以是否需要采用另一种方法,如接口或抽象基类

#13


或者有同样能实现这样功能的设计模式可以使用?

#14


MSDN上的解释是这样的
错误消息 
“identifier”:创建变量类型的实例时无法提供参数

如果对类型参数上的 new 运算符的调用带有参数,则会发生此错误。可以使用未知参数类型上的 new 运算符调用的唯一构造函数是不带参数的构造函数。如果需要调用另一个构造函数,请考虑使用类类型约束或接口约束。

但是用接口约束,接口不可以有构造函数的啊,用了类类型约束,还是同样的错误-_-!

#15


最终写出来的东西是这样的:

public IList<T> GetGroupInfoList<T>(Guid uid): where T: myT
        {
            IList<T> list = new List<T>();
            T t = new T(uid) // myT的构造函数均是这样的 myT(Guid uid)
            list.add(t)
            return list;
        }

#16


你把问题搞复杂了,太有才了,所以反而整出了问题。

对于:
            如果T是XX类,则SQL语句为=“...”
            如果T是YY类,则SQL语句为=“...”

            执行数据查询
      
            返回的字段填充到object[]中
的处理应该是各种T从myT继承而来的,各个T在new(guid)构造方法中只需要知道自己的SQL,调用myT中定义的Protected的数据查询方法,把object[]消化在自己类型内部。

面向对象不是大杂烩,多态的关键就是根本上消去对类型的“switch...case...”或者说连续的“if...else if....”结构。你看看各种多态应用,是不是这样的?

这样做了之后,不用在设计一个类型处理流程时把其它类型都杂烩在一起,扩展的时候也不需要重构。而你的原来的那段代码,当T是其它类型时,就必须重构,否则逻辑就彻底乱了——没有考虑所有子类而仅仅考虑了两种子类,所以一看就是用面向对象的语法代码来偷运结构化的设计思想的。

#17


结构化在处理扩展问题是,用一大堆“switch....case....”来判断,甚至入侵入早期的面向对象设计模式中被表述成“控制类型”之类的多余设计。实际上,这些在面向对象方法中,都可以通过比较纯粹、简练的多态结构来解决。“设计模式”是相当繁琐、冗长、八股的一本书。纯粹的面向对象在设计软件时更为简洁方便。

#18


哦,实例化对象可以从类型得到constructor方法然后invoke,包括guid参数。

#19


嗯,又发现我写的那段代码忘记写new约束了。

自己改一下吧。总之是泛型应该当作类型扩展用,不要当作类型聚合用。

#20


先谢谢sp1234(嘿嘿) :)
寝室快熄灯了,明天来看

#21


studing

#22


但是我是在分层设计中这样做的。类型都是Model,而那个方法在DAL中的
该怎么设计呢?

#23


最好是先定义一个基类baseGroup,其中包含带有构造函数含有参数object[]
然后在泛型的约束中where T: baseGroup
再解决你的判断类型的问题

#24


实际上在泛型的方法中包含判断类型这样的做法我觉得不是很妥当的

#25


@sp1234(嘿嘿)
兄弟太有才了,嘿嘿:)

按sp1234所说那样,更好的应该就是XX,YY同时继承于myT,在XX,YY的类中执行SQL语中。无需在进行typeof()判断。
hoho

#26


menuvb(戏子,白日做梦)
那我不是要在object中 参入数据层的东西

#27


1、不要生搬硬套,自己觉得该怎么写就怎么写
2、不要拘泥于形式和理论,所有的一切,都是为了简化代码

#28


Ivony(授人以鱼不如授人以渔,上海谋生) 
分清楚了 有助于系统的更改与扩展

#29


很简单啊,代码如下:
 class TMenu
    {
        public TMenu()
        {
        }
        public string getName()
        {
            return "AAA";
        }
    }
    class menu<T> where T : TMenu, new()

    {
        public T obj;
        public menu()
        {
        }
        public menu(T obj)
        {
            this.obj = obj;
        }
        public string GetStr()
        {
            return obj.getName();
        }
         public string MyCreateObj()
         {
               T KK = new T();//注意这里创建哦.
              return   KK.getName();
         }
    } 

    class Test
    {
       
        static void Main()
        {
            menu<TMenu> MyMenu = new menu<TMenu>(new TMenu());
            System.Console.WriteLine(MyMenu.MyCreateObj());
        }
    }

#30


关键的就是
class menu <T> where T : TMenu,  new() 

#31


to:sp1234
你的实例代码是有问题的,如果你加了new(),最后创建类的实例时会因构造函数不能接受参数而编译不通过。而你要不加new(),就不能实例化。

我怀疑这是C#语言在泛型编程上的一个局限。

#32


我试过了,要么提示:

创建变量类型的实例时无法提供参数

要么提示:

变量类型“W”没有 new() 约束,因此无法创建该类型的实例

总之就是不能在实例化对象时为构造函数提供参数。