目前我正在与那个“神奇的弦乐”问题作斗争:
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
}
}
现在我收到错误消息我写在我的主题标题中。我认为问题是这个字符串不是“非编译时”的常量。因此,要求切换的唯一可能方法是通过明确确定该案例字符串的值。我的问题是,如果我重命名MyDataField
类,我不会收到编译错误。因此,无论如何,这些类中有90%是通用的。这些是在switch语句的default
中处理的。除了明确确定案例值的价值之外,还有其他方法吗?
请不要争论这种方法的意义。我刚刚写了这个以更简单的方式来说明我的问题
答案 0 :(得分:11)
只需使用if
:
Type type = myField.GetType();
if (type == MyDataField.GetType())
{
…
}
else if (type.ToString() == "MyDataField")
{
…
}
else
{
…
}
您甚至不需要比较类型名称,而是直接比较Type
个对象(引用)。
答案 1 :(得分:6)
我建议您使用规范§8.7.2,其中规定了switch-label
的语法:
switch-label:
case constant-expression:
default:
简单地说,case标签在编译时必须是常量。请注意,typeof(MyDataField).ToString()
不是编译时常量(它可能看起来不变,但不是因为它在编译时无法完全评估)。规范的第7.19节非常清楚地说明了常量是什么
您需要将其重新编码为if/else if/else
。
答案 2 :(得分:1)
case语句需要一个常量值,所以你有
case MyDataField.GetType().ToString():
您需要将其更改为您要查找的特定字符串:
case "BR549":
break;
如果您要确定字段类型,可以执行以下操作:
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;
}
答案 3 :(得分:1)
使用C#7的新pattern matching feature,我会用以下方式解决它。
这是一个简单的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; }
}
这里有一个FieldOperator
类,可以对Field
的列表进行任意更改
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;
}
}
}
}
测试这些“操作”的正确性
[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));
}
答案 4 :(得分:0)
使用函数重载,也许是dynamic
关键字。或使用访客模式。无论哪种方式都可以根据变量的运行时类型进行调度。