为什么typeof(int).ToString()不是常量?

时间:2017-01-05 16:37:05

标签: c# compiler-errors switch-statement tostring typeof

我正在尝试这样做:

const string intType = typeof(int).ToString();
switch (typeof(MyT).ToString())
{
    case intType:
    {
        return "int";
        break;
    }
    ...
}

但是编译器说:

  

错误CS0133:分配给'intType'的表达式必须是常量

据我所知,typeof运算符在编译时工作。那么,怎么了?

4 个答案:

答案 0 :(得分:12)

  

据我所知,typeof运算符在编译时工作。

知道,因为知识必须 true 。你在哪里得到typeof在编译时执行的想法?它产生一个非常数对象。然后无法保证ToString每次运行时都不会生成不同的字符串,因此也不能将其视为常量。

  

那么,出了什么问题?

你是从错误的信念中推理出来的。

C#规范清楚地描述了表达式作为编译时常量必须满足的条件。这些条件包括不包含任何typeof运算符或方法调用的表达式。

但这里有更大的问题。我假设MyT是泛型类型参数,这意味着您正在尝试打开泛型类型参数的值。这几乎总是错误的。

你真的想做什么?你真的想解决什么问题?因为到目前为止你所展示的这段代码表明你正在走一条非生产性的道路去解决真正的问题。

答案 1 :(得分:2)

将类型MyT与已知类型进行比较的唯一方法是检查其Type对象是否相等。这可以按如下方式完成:

if (typeof(MyT) == typeof(int)) return "int";
if (typeof(MyT) == typeof(decimal)) return "decimal";
// etc...

您无法在switch中使用此方法,因为(目前)switch要求所检查的项目属于简单类型:

switch (typeof(T)) // Compile error: "switch expression or case label must be a bool,
                   // char, string, integral, enum, or corresponding nullable type"
{
    case typeof(int): return "int";
    case typeof(decimal): return "decimal";
    // ...
}

另外,正如其他人已经说过的那样,以这种方式检查类型几乎总是意味着可以通过应用不同的面向对象原则来改进您的方法。

E.g。而不是MyMethod<MyT>(MyT item)MyT进行类型检查,请考虑制作MyMethod(int item)MyMethod(decimal item)等。

答案 2 :(得分:1)

我认为,很明显,他想要实现的目标:

他希望在switch-case而不是if-elseif中检查类型是否相等。说实话,为什么不呢?但他怎么能实现这个目标呢?

  1. 第一个选项:等待C# 7.0。是的,将来有可能这样做!

  2. 第二个选项:使用字符串。但case字符串需要保持不变。那么精彩的nameof

  3. 呢?

    我刚试过这个“美女”并且它有效,所以这可能解决了你的问题:

    switch (typeof(Int32).Name)
    {
        case nameof(Int32):
             Console.WriteLine("It's an Int32!");
             break;
        case nameof(Double):
             Console.WriteLine("It's a Double");
             break;
     }
    

答案 3 :(得分:-1)

如果您只是想获取描述对象类型的字符串,则只需要调用.GetType()。

例如,以下是一个小函数,它将返回对象类型的字符串名称。

 static string GetTypeString(object obj)
 {
      return obj.GetType().FullName;
 }

这将返回到对象的完整路径。在int的情况下,它将返回System.Int32。如果您只想要Int32部分,请改用GetType()。Name。

另外,你不需要休息;如果你有回报,在交换机中;

如果您需要为某些类型运行特定代码,或者您想要返回的特定字符串,则可以对上面返回的值使用字符串。例如:

   static string GetSimpleType(object obj)
    {
        var stringRepresentation = GetTypeString(obj);
        switch (stringRepresentation)
        {
            case "System.Int64":
            case "System.Int32":
                return "int";

            default:
                return stringRepresentation;
        }
    }
对于没有案例的所有内容,

default是一个catch all语句。把它想象成别的。

在上面的例子中,我们为int,Int32和Int64返回相同的值。如果案例标签为空,则案例标签可以覆盖其他案例标签。

您可以通过运行简单脚本找到编写交换机所需的所有值,并对字符串值进行硬编码,因为对于相同类型,它们将始终相同。如果字符串不同,则类型不同。

最后,如果您要比较类型,if和if else的效果会更好:

        static string GetSimpleType(object obj)
        {
           if (obj.GetType() == typeof(int))
           {
               return "int"; 
           }

            return obj.GetType().ToString();
        }