Có bất kỳ hàm Parse () chung chung nào sẽ chuyển đổi một chuỗi thành bất kỳ kiểu nào bằng cách sử dụng phân tích cú pháp không?


91

Tôi muốn chuyển đổi một chuỗi thành một kiểu chung như inthoặc datehoặc longdựa trên kiểu trả về chung.

Về cơ bản, một hàm như thế Parse<T>(String)trả về một loại mục T.

Ví dụ, nếu một int đã được truyền thì hàm phải thực hiện int.parsenội bộ.

Câu trả lời:


132

System.Convert.ChangeType

Theo ví dụ của bạn, bạn có thể làm:

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

Để đáp ứng yêu cầu "loại trả lại chung", bạn có thể viết phương thức mở rộng của riêng mình:

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

Điều này sẽ cho phép bạn làm:

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

mát mẻ, nhưng điều kỳ lạ mang tên mình ChangeType, vì vậy tôi sẽ nghĩ rằng chức năng này không một số loại đúc và không phân tích cú pháp
Karim

7
MSDN cho biết nó chỉ đơn giản là một trình bao bọc tìm ra phương pháp chuyển đổi phù hợp trên đối tượng nguồn, yêu cầu nó triển khai giao diện IConvertible.
Ani

Nếu nó cần phải thực hiện, IConvertablebạn cũng không nên hạn chế T, tức là T ChangeType<T>(this object obj) where T : IConvertable?
Liam

2
@Liam: Không, objphải vậy IConvertible, nhưng không có cách nào để xác định điều đó tại thời điểm biên dịch.
Ani

nếu tôi cần một cái gì đó như TryChangeType trả về null hoặc false trong trường hợp thất bại? Chỉ bằng cách bắt ngoại lệ?
Vô vọng

21

Có vẻ như tôi đã quá muộn để trả lời về chủ đề này. Nhưng đây là cách thực hiện của tôi:

Về cơ bản, tôi đã tạo một phương thức Extention cho lớp Object. Nó xử lý tất cả các kiểu, tức là nullable, các lớp và cấu trúc.

 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 này là câu trả lời tốt hơn vì nó cũng chứa các "nullable" -aspect
Ole Albers

có lý do cụ thể nào mà bạn đang sử dụng TypeDescriptorcho các kiểu nullable và Convert.ChangeTypecho những kiểu không thể null không? Toàn bộ trykhối này chỉ có thể được giảm xuống chỉ còn TypeConverter2 dòng mã và nó sẽ hoạt động cho cả hai, nullable và non-nullable.
IMujagic


8

phiên bản rõ ràng hơn của câu trả lời của 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

Có một số quy ước trong .NET để chuyển đổi các đối tượng thuộc loại này sang loại khác.

Nhưng những phương pháp này chậm hơn nhiều so với thông thường của bạn T.Parse(string), gây ra hiện tượng đấm bốc và liên quan đến nhiều phân bổ mỗi khi bạn muốn chuyển đổi một giá trị duy nhất.

Đối với ValueString , tôi đã chọn tìm một phương pháp phân tích cú pháp tĩnh, phù hợp của kiểu sử dụng phản chiếu, xây dựng biểu thức lambda gọi nó và lưu vào bộ nhớ cache của đại biểu đã biên dịch để sử dụng trong tương lai (Xem câu trả lời này để biết ví dụ).

Nó cũng dự phòng cho các cách tôi đã đề cập ở trên nếu loại không có phương pháp phân tích cú pháp phù hợp (Xem phần hiệu suất trong readme).

var v = new ValueString("15"); // struct
var i = v.As<int>(); // Calls int.Parse.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.