簡體   English   中英

C#在運行時切換對象類型

[英]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

這取決於設計的重要性:

  • o.GetType()/ o.GetType()上的if語句或switch語句。名稱
  • 實現一種IShow-Interface(使用方法void Show(object o)並使用Dictionary將類型映射到此接口的實現並僅使用
     if (TryGetValue(o.GetType, out show)) show.Show(o); 
  • 只是堅持下去,讓對象告訴故事(覆蓋ToString)...是的你不想要這個,但恕我直言這最好的方法來做到這一點

您是否考慮以更友好的方式覆蓋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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM