[英]C# Switch on Object Type at Runtime
我有一個List<object>
。 我想循環遍歷列表並以比o.ToString()
更友好的方式打印出值,以防某些對象是布爾值或日期時間等。
你將如何構造一個我可以調用MyToString(o)
的函數並返回一個正確格式化的字符串(由我指定)作為其實際類型?
您可以在.NET 4.0中使用dynamic關鍵字 ,因為您正在處理內置類型。 否則,你將使用多態。
例:
using System;
using System.Collections.Generic;
class Test
{
static void Main()
{
List<object> stuff = new List<object> { DateTime.Now, true, 666 };
foreach (object o in stuff)
{
dynamic d = o;
Print(d);
}
}
private static void Print(DateTime d)
{
Console.WriteLine("I'm a date"); //replace with your actual implementation
}
private static void Print(bool b)
{
Console.WriteLine("I'm a bool");
}
private static void Print(int i)
{
Console.WriteLine("I'm an int");
}
}
打印出來:
I'm a date
I'm a bool
I'm an int
這取決於設計的重要性:
if (TryGetValue(o.GetType, out show)) show.Show(o);
您是否考慮以更友好的方式覆蓋ToString()?
這是一個帶注釋的工作示例。 它使用通用的Type of Type和Lambda Func。
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
// a custom class
public class MyPerson
{
public string FN { get; set; }
public string LN { get; set; }
}
static void Main(string[] args)
{
// your prebuilt dictionary of Types to Lambda expressions to get a string
Dictionary<Type, Func<object, String>> MyToStringLookup = new Dictionary<Type, Func<object, string>>()
{
{typeof(String), new Func<Object, String>( obj => obj.ToString() )},
{typeof(DateTime), new Func<Object, String>( obj => ((DateTime)obj).ToString("d") )},
{typeof(MyPerson), new Func<Object, String>( obj => (obj as MyPerson).LN )},
};
// your list of objects
List<Object> MyObjects = new List<Object>()
{
"abc123",
DateTime.Now,
new MyPerson(){ FN = "Bob", LN = "Smith"}
};
// how you traverse the list of objects and run the custom ToString
foreach (var obj in MyObjects)
if (MyToStringLookup.ContainsKey(obj.GetType()))
System.Console.WriteLine(MyToStringLookup[obj.GetType()](obj));
else // default if the object doesnt exist in your dictionary
System.Console.WriteLine(obj.ToString());
}
}
}
您唯一的選擇是if-else-if結構。 switch不允許打開類型,因為switch結構需要一個具有互斥值的可枚舉集合(並且一個對象可以是幾種類型)。
編輯阿巴斯評論:
GetType()。名稱有效但會導致您在此上下文中出現潛在錯誤,因為它可以返回您不知道的類型。 即使一個對象存儲為類型A,GetType()。如果B繼承A,Name也可能返回“B”。如果你在執行切換的方法的上下文中不知道B(它可能是一個類型來自另一個繼承了當前庫之一的庫,它可能是在你編寫方法后添加的類型),你會在偽類型切換中錯過它。 如果你寫if(obj is A)
,你就不會。
例如,如果我寫這個:
/// <summary>
/// Displays ":)" if obj is a Foo
/// </summary>
public static void CaseType(object obj)
{
switch(obj.GetType().Name)
{
case "Foo":
MessageBox.Show(":)");
break;
default:
MessageBox.Show(":(");
break;
}
}
評論是謊言,因為
public class Bar : Foo
{
}
public static void CaseTypeSpecialized()
{
Foo obj = new Bar();
CaseType(obj);
}
將顯示“:(”。
如果你寫,它會工作
/// <summary>
/// Displays ":)" if obj is a Foo
/// </summary>
public static void CaseType(object obj)
{
if (obj is "Foo")
{
MessageBox.Show(":)");
}
else
{
MessageBox.Show(":(");
}
}
這是switch的概念 ,與非互斥的值不兼容。 這就是為什么當值不是獨占時打開Flags枚舉時可能會出現編譯錯誤的原因。
這樣的事情可能會讓你在路上:
private static String MyToString(object o)
{
var val = "";
switch (o.GetType().Name)
{
case "Boolean": val = ((bool)o) ? "this is true" : "this is false"; break;
case "DateTime": val = "The date is: " + ((DateTime)o); break;
case "Int32": val = "The number-value is: " + (int)o; break;
}
return val;
}
希望這可以幫助! ;)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.