Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#泛型方法和列表_C#_Generics - Fatal编程技术网

c#泛型方法和列表

c#泛型方法和列表,c#,generics,C#,Generics,我想了解为什么下面的代码不起作用,以及如何修复它 如果T是双倍或长的,为什么T不接受双倍或长的铸件 private IList<T> GetGenericList<T>(bool isDouble) where T : double, long { IList<T> Result = new List<T>(); if (isDouble) { T Value

我想了解为什么下面的代码不起作用,以及如何修复它

如果T是双倍或长的,为什么T不接受双倍或长的铸件

    private IList<T> GetGenericList<T>(bool isDouble) where T : double, long
    {
        IList<T> Result = new List<T>();

        if (isDouble)
        {
            T Value = 2.5; // does not compile
            Result.Add(Value);
        }
        else
        {
            T Value = 2; // does not compile
            Result.Add(Value);
        }

        return Result;
    }
private IList GetGenericList(bool isDouble),其中T:double,long
{
IList结果=新列表();
if(isDouble)
{
T值=2.5;//不编译
结果:增加(价值);
}
其他的
{
T值=2;//不编译
结果:增加(价值);
}
返回结果;
}
[更新] 好了,大家不要紧张!让我明白你说的话!:)

c#中泛型的原理是什么

如果我将de代码更改为以下示例?(开箱即用,这只是一个例子,请忽略de规则(if(isDouble),无论什么)

private IList GetGenericList(//参数的任何内容。。。
)其中T:double
{
IList结果=新列表();
T值=2.5;//不编译
结果:增加(价值);
返回结果;
}

谢谢,isDouble在运行时被赋予一个值。无论分支如何,这两个赋值在编译时都必须有意义


您正在尝试使用泛型执行一些原则上无法执行的操作。

代码无法工作的原因有三个:

  • 您的泛型约束要求类型继承自
    double
    long
    ,这是不可能的
  • double
    long
    不能用作常规约束,因为它们是密封的
  • 没有从
    double
    到未知类型的隐式转换
  • 前两个没有“修复”。最后一个修复将首先强制转换到
    对象

        if (isDouble)
        {
            T Value = (T)(object)2.5; // does not compile
            Result.Add(Value);
        }
        else
        {
            T Value = (T)(object)2; // does not compile
            Result.Add(Value);
        }
    
    无法让方法完全按照您希望的方式工作,因为无法将
    T
    约束为
    double
    long
    。您可以使用反射检查类型,如果不是其中之一,则抛出异常,但无法在编译时强制执行

    核心问题是您的代码不是泛型的。真正的泛型代码不关心
    T
    是什么(对一些非常广泛的参数进行模化,比如它必须实现一些接口)。调用者需要确定什么是
    T
    ,而不是方法,因此根据
    T
    的实际类型具有不同逻辑的任何东西通常都是代码气味。这似乎只是一个学习练习,但如果您在现实生活中需要此功能,我建议使用两种不同的方法:

    private IList<double> GetDoubleList()
    {
        IList<double> Result = new List<double>();
    
        double Value = 2.5; 
        Result.Add(Value);
    
        return Result;
    }
    private IList<long> GetLongList()
    {
        IList<long> Result = new List<long>();
    
        long Value = 2; 
        Result.Add(Value);
    
        return Result;
    }
    
    private IList GetDoubleList()
    {
    IList结果=新列表();
    双值=2.5;
    结果:增加(价值);
    返回结果;
    }
    私有IList GetLongList()
    {
    IList结果=新列表();
    长值=2;
    结果:增加(价值);
    返回结果;
    }
    
    它并不比你开始时长多少,有一点重复,但不多,它是完全类型安全的,并且在方法中没有类型歧义

    接下来,您可以将冗余代码重构为泛型方法(在这种情况下,您不需要约束它,因为您可以从调用方法控制类型):

    private IList GetList(T值)
    {
    IList结果=新列表();
    结果:增加(价值);
    返回结果;
    }
    私有IList GetDoubleList()
    {
    返回GetList(2.5);
    }
    私有IList GetLongList()
    {
    返回GetList(2);
    }
    
    要回答您的问题,请参阅:

    对于您当前只希望处理
    double
    long
    的问题,您可以按照D Stanley的建议,只需处理其他类型的问题。以下是一个示例:

      private IList<T> GetGenericList<T>()
      {
         Type parmType = typeof(T);
         if (!parmType.Equals(typeof(double)) && !parmType.Equals(typeof(long)))
         {
            return null;
         }
         else
         {
            IList<T> Result = new List<T>();
    
            if (parmType.Equals(typeof(double)))
            {
               T Value = (T)(object)2.5;
               Result.Add(Value);
            }
            else
            {
               T Value = (T)(object)2L;
               Result.Add(Value);
            }
    
            return Result;
         }
      }
    
    private IList GetGenericList()
    {
    类型parmType=类型(T);
    如果(!parmType.Equals(typeof(double))&&!parmType.Equals(typeof(long)))
    {
    返回null;
    }
    其他的
    {
    IList结果=新列表();
    if(parmType.Equals(typeof(double)))
    {
    T值=(T)(对象)2.5;
    结果:增加(价值);
    }
    其他的
    {
    T值=(T)(对象)2L;
    结果:增加(价值);
    }
    返回结果;
    }
    }
    
    现在,当我这样使用它时:

         List<double> lDbl = (List<double>)GetGenericList<double>();
         List<long> lLng = (List<long>)GetGenericList<long>();
         List<string> lStr = (List<string>)GetGenericList<string>();
    
    List lDbl=(List)GetGenericList();
    List lLng=(List)GetGenericList();
    List lStr=(List)GetGenericList();
    

    最后我得到了
    lDbl
    lLng
    中的预期值,包括正确的数据类型。但是,
    lStr
    被设置为
    null
    ,因为这是我让它处理除
    double
    long
    之外的类型的方式。你可以很容易地在其中抛出一个异常。

    你没有理由这么做需要提供isDouble作为参数;T的类型可以在运行时确定:
    type-typeParameterType=typeof(T)
    :double,long
    意思是double和long,也就是说,这是无稽之谈。我印象深刻的是,这甚至会compile@Jonesopolis它没有编译;首先:@Blorgbeard不,它没有。OP给人的印象是它编译了。我很笨。真正奇怪的是,我得到了一个带有
    t Value=(t)(object)的InvalidCastException2、 
    。我处理它的方法是使用
    T Value=(T)(object)2L;
    这是因为实际类型是
    int
    ,因为它是整数文本。因为引用强制转换要求实际类型是兼容的(而不是可转换的)强制转换将在运行时失败。这是我在事后检查它时所想到的。我同意您的编辑,尤其是接受任何值的最终重构。在泛型方法中进行检查会失败。我也同意这似乎是一个学习练习。将中心思想保留在一个方法中是一个很好的示例。这就是我一直在看的…谢谢!!谢谢克里斯和所有人!演员阵容怎么样了?
    List lDbl=GetGenericList();
    应该没问题,对吧
      private IList<T> GetGenericList<T>()
      {
         Type parmType = typeof(T);
         if (!parmType.Equals(typeof(double)) && !parmType.Equals(typeof(long)))
         {
            return null;
         }
         else
         {
            IList<T> Result = new List<T>();
    
            if (parmType.Equals(typeof(double)))
            {
               T Value = (T)(object)2.5;
               Result.Add(Value);
            }
            else
            {
               T Value = (T)(object)2L;
               Result.Add(Value);
            }
    
            return Result;
         }
      }
    
         List<double> lDbl = (List<double>)GetGenericList<double>();
         List<long> lLng = (List<long>)GetGenericList<long>();
         List<string> lStr = (List<string>)GetGenericList<string>();