มีฟังก์ชัน Parse () ทั่วไปที่จะแปลงสตริงเป็นประเภทใด ๆ โดยใช้การแยกวิเคราะห์หรือไม่


93

ฉันต้องการแปลงสตริงเป็นประเภททั่วไปเช่นintหรือdateหรือlongตามประเภทการส่งคืนทั่วไป

โดยทั่วไปฟังก์ชั่นเหมือนที่ส่งกลับรายการของการพิมพ์ Parse<T>(String)T

ตัวอย่างเช่นถ้า int ถูกส่งผ่านฟังก์ชันควรทำint.parseภายใน

คำตอบ:


134

System.Convert.ChangeType

ตามตัวอย่างของคุณคุณสามารถทำได้:

int i = (int)Convert.ChangeType("123", typeof(int));
DateTime dt = (DateTime)Convert.ChangeType("2009/12/12", typeof(DateTime));

เพื่อให้เป็นไปตามข้อกำหนด "ประเภทการคืนสินค้าทั่วไป" คุณสามารถเขียนวิธีการขยายของคุณเอง:

public static T ChangeType<T>(this object obj)
{
    return (T)Convert.ChangeType(obj, typeof(T));
}

สิ่งนี้จะช่วยให้คุณทำ:

int i = "123".ChangeType<int>();

เจ๋ง แต่ที่แปลกคือมันมีชื่อว่า ChangeType ดังนั้นฉันคิดว่าฟังก์ชั่นนี้มีการร่ายและไม่แยกวิเคราะห์
Karim

7
MSDN กล่าวว่ามันเป็นเพียง wrapper ที่ค้นหาวิธีการแปลงที่ถูกต้องบนวัตถุต้นทางโดยต้องใช้อินเทอร์เฟซ IConvertible
Ani

หากจำเป็นต้องใช้IConvertableคุณไม่ควรบังคับTด้วยเช่นกันT ChangeType<T>(this object obj) where T : IConvertable?
Liam

2
@ เลียม: ไม่objต้องเป็นอย่างIConvertibleนั้น แต่ไม่มีทางระบุได้ในเวลาคอมไพล์
Ani

ถ้าฉันต้องการบางอย่างเช่น TryChangeType ที่คืนค่า null หรือ false ในกรณีที่ล้มเหลว? โดยการจับข้อยกเว้นเท่านั้น?
Hopeless

22

ดูเหมือนว่าฉันจะสายเกินไปที่จะตอบกระทู้นี้ แต่นี่คือการใช้งานของฉัน:

โดยพื้นฐานแล้วฉันได้สร้างเมธอด Extention สำหรับคลาส Object มันจัดการทุกประเภทเช่น nullable คลาสและโครงสร้าง

 public static T ConvertTo<T>(this object value)
           {
               T returnValue;

               if (value is T variable)
                   returnValue = variable;
               else
                   try
                   {
                       //Handling Nullable types i.e, int?, double?, bool? .. etc
                       if (Nullable.GetUnderlyingType(typeof(T)) != null)
                       {
                           TypeConverter conv = TypeDescriptor.GetConverter(typeof(T));
                           returnValue = (T) conv.ConvertFrom(value);
                       }
                       else
                       {
                           returnValue = (T) Convert.ChangeType(value, typeof(T));
                       }
                   }
                   catch (Exception)
                   {
                       returnValue = default(T);
                   }

               return returnValue;
           }

IMHO นี่เป็นคำตอบที่ดีกว่าเพราะมันมี "nullable" ด้วย
Ole Albers

มีเหตุผลเฉพาะหรือไม่ว่าทำไมคุณถึงใช้TypeDescriptorสำหรับประเภทที่เป็นโมฆะและConvert.ChangeTypeสำหรับประเภทที่ไม่เป็นโมฆะ tryบล็อกทั้งหมดนี้สามารถลดลงเหลือเพียงTypeConverter2 บรรทัดของโค้ดและจะใช้ได้กับทั้งสองอย่างเป็นโมฆะและไม่เป็นโมฆะ
IMujagic

9

System.Convert.ChangeTypeไม่แปลงเป็นประเภทใด ๆ คิดดังต่อไปนี้:

  • ประเภทที่เป็นโมฆะ
  • enums
  • Guid เป็นต้น

การแปลงเหล่านี้เป็นไปได้ด้วยการใช้ ChangeTypeนี้


9

คำตอบของ Pranayเวอร์ชันที่สะอาดกว่า

public static T ConvertTo<T>(this object value)
{
    if (value is T variable) return variable;

    try
    {
        //Handling Nullable types i.e, int?, double?, bool? .. etc
        if (Nullable.GetUnderlyingType(typeof(T)) != null)
        {
            return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(value);
        }

        return (T)Convert.ChangeType(value, typeof(T));
    }
    catch (Exception)
    {
        return default(T);
    }
}

0

มีอนุสัญญาสองสามข้อใน. NET เพื่อแปลงวัตถุประเภทหนึ่งเป็นอีกประเภทหนึ่ง

แต่วิธีการเหล่านี้ช้ากว่าปกติของคุณT.Parse(string)มากทำให้เกิดการชกมวยและเกี่ยวข้องกับการจัดสรรจำนวนมากในแต่ละครั้งที่คุณต้องการแปลงค่าเดียว

สำหรับValueStringฉันเลือกที่จะหาวิธีการแยกวิเคราะห์แบบคงที่ที่เหมาะสมโดยใช้การสะท้อนกลับสร้างนิพจน์แลมบ์ดาที่เรียกมันและแคชตัวแทนที่คอมไพล์แล้วเพื่อใช้ในอนาคต (ดูตัวอย่างคำตอบนี้ )

นอกจากนี้ยังเปลี่ยนกลับไปใช้วิธีที่ฉันกล่าวถึงข้างต้นหากประเภทไม่มีวิธีการแยกวิเคราะห์ที่เหมาะสม (ดูส่วนประสิทธิภาพใน readme)

var v = new ValueString("15"); // struct
var i = v.As<int>(); // Calls int.Parse.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.