C#返回T的问题

时间:2010-12-04 21:01:52

标签: c#

我有一个方法可以将数字从字符串转换为T,例如int

public static T GetItemIdFromUrl<T>(string itemName)
{
   try
   {
      ...
      int ad_id = int.Parse(stringNumber);

      return (T)(object)ad_id;
   }
   catch 
   {
      return (T)(object)-1;
   }
}

但结果我有一个十六进制代码0xffffffa5而不是91。为什么?

4 个答案:

答案 0 :(得分:5)

嗯,很难知道为什么它在不知道输入字符串的情况下返回0xffffffa5,但是如果T不是int或者具有底层基类型的枚举,那么你的代码将抛出异常int。例如,如果T为double将抛出。你的方法并不是通用的 - 它尝试返回的值总是int。为什么您的方法不仅仅被声明为返回int?如果您想要从int转换为其他类型(doublelong,等等),请在转让时完成转换。除非Tint或适当的枚举(后者似乎不太可能),否则代码中的取消装箱转换将无效

需要注意的一点是,0xffffffa5是-91的位模式。你是否有可能只在调试器中看到了这个结果,结果是-91而不是91?

答案 1 :(得分:3)

即使您打算对不同数字类型(例如doubledecimal等)的处理进行泛化,也不是这样做的。当您object,然后取消装箱Tit will only work if the boxed type actually is T时。换句话说,它将为您执行类型转换。

object到您想要的任何类型转换的唯一方式(据我所知)是使用Convert类:

return (T)Convert.ChangeType(ad_id, typeof(T));

即使这很脆弱,显然也是如此(因为如果T是非数字类型,它将无法工作);但至少它不会在你想要覆盖的所有情况下抛出异常。 (当前实施的方法将针对除T之外的每个int投放。)

答案 2 :(得分:1)

我认为你对仿制药是什么以及它们应该如何被使用有一个根本的误解。仿制药的全部意义在于,在不失去类型安全的情况下,有利于处理不同的类型,这就是当你转向object时发生的事情

据说Jon Skeet可能是正确的,这可能是调试器显示结果的方式。

答案 3 :(得分:0)

我认为你正在做其他显示省略号(...)的事情:

   try
   {
      ...
      int ad_id = int.Parse(stringNumber);

      return (T)(object)ad_id;
   }

因为我尝试了你的样本,我得到了回复int

目前,你真的没有办法确保你的回归能够奏效。您的方法将依赖于非常具体的信息。提供更多信息,如果您有省略号,可以推荐更好的解决方案。 正如乔恩所提到的那样,一个可以为空的int?会更好。测试条件,如果不是正确的退货,您可以检查myInt.HasValue

我一直在思考这个问题的完整解决方案,并提出以下建议:

static List<Type> numerics = new List<Type>();

static void Main(string[] args)
{
    numerics.Add(typeof(Decimal));
    numerics.Add(typeof(Double));
    numerics.Add(typeof(Int16));
    numerics.Add(typeof(Int32));
    numerics.Add(typeof(Int64));
    numerics.Add(typeof(Single));
    numerics.Add(typeof(UInt16));
    numerics.Add(typeof(UInt32));
    numerics.Add(typeof(UInt64));

    Console.WriteLine("StringNumber 55:  {0} {1}", typeof(int), GetItemIdFromUrl<int>("55"));
    Console.WriteLine("StringNumber 5B99:  {0} {1}", typeof(int), GetItemIdFromUrl<int>("5B99"));

    Console.ReadKey();
}

public static T GetItemIdFromUrl<T>(string stringNumber)
{
    try
    {
        if (numerics.Contains(typeof(T)))
            return (T)Convert.ChangeType(stringNumber, typeof(T));
        else
            return default(T);
    }
    catch (ArgumentException argEx)
    {
        Console.WriteLine("Exception\r\n{0}", argEx);
        return default(T);
    }
    catch (FormatException formatEx)
    {
        Console.WriteLine("Exception\r\n{0}", formatEx);
        return default(T);
    }
}

从第二个WriteLine,您将能够看到如果传递了无效数字会发生什么。当然,我添加了Exception消息,以便您可以看到它们会返回什么。它可能不是一个迷人的解决方案,但我认为它是可行的。

我也想到了这个:

public static class GetNumeric<T>
{
    public static Func<string, T> Value = stringValue => (T)Convert.ChangeType(stringValue, typeof(T));
}

虽然我仍然会将调用包裹在try/catch块中。