C# switch 语句:“需要一个常量值”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9004811/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
switch statement: "a constant value is expected"
提问by Michael Schnerring
Currently I'm fighting with that "magical strings" issue:
目前我正在与“神奇的字符串”问题作斗争:
public class MyDataField
{
// class definition
}
// exuecuted method
public void SwitchMultipleDataFields()
{
var myField = new MyDataField();
switch(myField.GetType().ToString())
{
// only case, which works
case "MyDataField":
// case operations
break;
// other option:
case typeof(MyDataField).ToString():
// case operations
break;
// other cases of other FieldTypes
}
}
Now I get the error Message I've written in the title of my thread. I think the problem is that this string is not a constant while "non-compile-time". So the only possible way to ask switch this is via explicitly determining the value of that case string. My problem just is that I don't get an compile error in case I'd rename the MyDataFieldclass. So 90% of these classes are generic anyway. These are handled in the defaultof the switch statement. Isn't there another way than explicitly determining the value of the case value?
现在我收到了我写在我的线程标题中的错误消息。我认为问题在于这个字符串在“非编译时”时不是常量。因此,要求切换的唯一可能方法是通过明确确定该 case 字符串的值。我的问题只是我没有收到编译错误,以防我重命名MyDataField类。所以这些类中的 90% 无论如何都是通用的。这些default在 switch 语句中处理。除了明确确定 case 值的值之外,还有其他方法吗?
Please don't argue about the sense of this method. I've just written that to illustrate my problem in an easier way
请不要争论这种方法的意义。我刚刚写的那是为了以更简单的方式说明我的问题
采纳答案by Michael Schnerring
With the new pattern matching featureof C# 7 I would solve it in the following manner.
使用C# 7的新模式匹配功能,我将通过以下方式解决它。
Here a simple Fieldand Documentclass
这里简单Field和Document类
public class Field
{
public string Label { get; set; }
}
public class Field<T> : Field
{
public T Value { get; set; }
}
public class Document
{
public string Content { get; set; }
}
And here a FieldOperatorclass which does some arbitrary changes to a list of Fields
这里是FieldOperator一个对Fields列表进行一些任意更改的类
public static class FieldOperator
{
public static void Operate(Field[] fields)
{
foreach (var field in fields)
{
field.Label = field.GetType().ToString();
switch (field)
{
case Field<Document> docField:
docField.Value.Content = "Foo Bar";
break;
case Field<int> intField:
intField.Value = 600842;
break;
default:
field.Label = "Oops";
break;
}
}
}
}
Testing for correctness of these "operations"
测试这些“操作”的正确性
[Test]
public void OperationsAreCorrect()
{
var docField = new Field<Document> {Value = new Document {Content = "Hello World"}};
var intField = new Field<int> {Value = 17};
var dateField = new Field<DateTime>();
FieldOperator.Operate(new Field[] {docField, intField, dateField});
Assert.IsTrue(docField.Label == docField.GetType().ToString());
Assert.IsTrue(intField.Label == intField.GetType().ToString());
Assert.IsTrue(dateField.Label == "Oops");
Assert.IsTrue(docField.Value.Content == "Foo Bar");
Assert.IsTrue(intField.Value == 600842);
Assert.IsTrue(dateField.Value == default(DateTime));
}
回答by Ondrej Tucny
Just use an if:
只需使用一个if:
Type type = myField.GetType();
if (type == MyDataField.GetType())
{
…
}
else if (type.ToString() == "MyDataField")
{
…
}
else
{
…
}
You even don't need to compare type names, but the Typeobjects (references) directly.
您甚至不需要比较类型名称,而是Type直接比较对象(引用)。
回答by jason
I refer you to the specification §8.7.2 which states for the grammar of a switch-label:
我建议您参阅规范 §8.7.2,其中规定了 a 的语法switch-label:
switch-label:
case constant-expression:
default:
Simply put, the case labels must be constants at compile-time. Note that typeof(MyDataField).ToString()is not a compile-time constant (it might look constant to you, but it's not because it can not be fully evaluated at compile time). §7.19 of the specification spells out very clearly what a constant is
简而言之,case 标签在编译时必须是常量。请注意,这typeof(MyDataField).ToString()不是编译时常量(它对您来说可能看起来是常量,但这不是因为在编译时无法对其进行完全评估)。规范的 §7.19 非常清楚地说明了什么是常数
You need to recode this as an if/else if/else.
您需要将其重新编码为if/else if/else.
回答by Ben Voigt
Use function overloading, and maybe the dynamickeyword. Or use the Visitor pattern. Either way gives you dispatch based on the runtime type of a variable.
使用函数重载,也许还有dynamic关键字。或者使用访问者模式。无论哪种方式,您都可以根据变量的运行时类型进行调度。
回答by ERukes
the case statement requires a constant value, so where you have
case 语句需要一个常量值,所以你有
case MyDataField.GetType().ToString():
you would need to change that to the specific string that you are looking for:
您需要将其更改为您要查找的特定字符串:
case "BR549":
break;
if you are trying to determine the field type, you can do something like this:
如果您正在尝试确定字段类型,您可以执行以下操作:
Int16 bob = 5;
TypeCode objType = (TypeCode) Enum.Parse(typeof(TypeCode), bob.GetType().ToString());
switch (objType)
{
case TypeCode.DateTime:
txtResults.Text = " - bob is a DateTime.";
break;
case TypeCode.Int16:
txtResults.Text = " - bob is an int16.";
break;
default:
txtResults.Text = " - bob is an unknown type.";
break;
}

