我知道typeof(T),但编译器没有.怎么修?

Luc*_*cas 9 c# generics

我正在尝试编写一个这样的方法:

public static T Test<T>()
{
  if (typeof(T)==typeof(string))
     return "1241";

  // do something else
}
Run Code Online (Sandbox Code Playgroud)

但我似乎无法弄清楚如何把它拉下来.我想根据调用方法的T类型返回值.我需要返回字符串,int,自定义类,List等.

实际的用例是一些自定义序列化代码,其中反序列化代码必须知道它应该生成的对象的类型.

澄清:上面的示例给出以下错误:无法将字符串转换为类型T.

理想的解决方案适用于值类型和引用类型,并且不包含用于重载解析的虚拟参数.

我开始怀疑是否存在理想的解决方案.

谢谢,卢卡斯

Luk*_*keH 13

中间演员object是不理想的,但这样的事情应该做的伎俩:

public static T Test<T>()
{
    if (typeof(T) == typeof(string))
        return (T)(object)"1241";

    // do something else
}
Run Code Online (Sandbox Code Playgroud)


M4N*_*M4N 6

您必须将返回值强制转换为T,例如类似于引用类型:

public static T Test<T>() where T : class
{
  if (typeof(T)==typeof(string))
     return "1241" as T;

  return default(T);
}
Run Code Online (Sandbox Code Playgroud)


Kon*_*lph 5

小心!该解决方案下面就无法正常工作(使用单声道验证gmcsC#编译器).

但是,它应该通过我阅读C#标准来工作,因为重载决策应该尽可能地支持方法的非泛型版本.ECMA-334的相关部分是25.1.7:"泛型类中的重载".此外,Eric Lippert似乎也在博客文章中这样说.

反馈将不胜感激:为什么这不能按预期工作?


你有不相关的类型和不相关的行为:这段代码尖叫" 使用重载!"

泛型适用于不相关的类型,但相同(或高度相似)的行为.

这样做(完成测试程序以重现行为):

using System;

class TestClass {
    public static T Test<T>() {
        return TestWith(default(T));
        // do something else
    }

    public static string TestWith(string dummy) {
        // Used only for `string`.
        return "string";
    }

    public static T TestWith<T>(T dummy) {
        // Used for everything else.
        return dummy;
    }

    static void Main() {
        Console.WriteLine("Expected \"0\", got \"{0}\"", Test<int>());
        Console.WriteLine("Expected \"string\", got \"{0}\"", Test<string>());
    }
}
Run Code Online (Sandbox Code Playgroud)

编译gmcs,这产生:

Expected "0", got "0"
Expected "string", got ""
Run Code Online (Sandbox Code Playgroud)

这里,该参数仅用于消除重载呼叫的歧义.这里不能使用显式通用参数,因为其中一个函数(特化string)不是通用的.

  • 得到它了.你看到的行为是正确的.重载决策分析总是在编译时发生,然后选择的重载被"烘焙"到生成的通用代码中.当编译泛型方法Test <T>()时,重载解析会尽可能地利用它可以处理的信息,即选择它知道将始终工作的方法 - TestWith <T>.编译器不知道将来某些调用者会有T字符串.如果你想让它选择给定_runtime_信息的最佳方法,C#4中的"动态"就可以做到这一点. (6认同)