Thật buồn cười, bạn nên đề cập đến nó bởi vì tôi đã rối tung xung quanh với một cái gì đó như thế này ngày khác:
using System;
using System.Reflection;
static class Example
{
public static Tuple<Boolean, T?> TryParse<T>(this String candidate)
where T : struct
{
T? value = null;
Boolean success = false;
var parser = ParsingBinder<T>.GetParser();
try
{
value = parser(candidate);
success = true;
}
catch (FormatException) { }
return new Tuple<Boolean,T?>(success, value);
}
}
static class ParsingBinder<T>
{
static Func<String, T> parser;
public static Func<String, T> GetParser()
{
if (parser == null)
parser = getParser();
return parser;
}
static Func<String, T> getParser()
{
MethodInfo methodInfo
= typeof(T).GetMethod(
"Parse", new [] { typeof(String) });
if (methodInfo == null)
throw new Exception(
"Unable to retrieve a \"Parse\" method for type.");
return (Func<String, T>)Delegate
.CreateDelegate(typeof(Func<String, T>), methodInfo);
}
}
Đó là một cách tiếp cận tương tự nhưng nghĩ về nó như một TryParse
phương pháp tốt hơn mà trả về một Tuple<Boolean, T?>
(điều này đòi hỏi .NET 4). Thuộc tính đầu tiên của tuple là giá trị boolean cho biết thành công hay thất bại của việc phân tích cú pháp và thuộc tính thứ hai là một giá trị nullable được gõ vào đối số kiểu chung sẽ là null
nếu phân tích cú pháp thất bại và giá trị nếu phân tích thành công.
Nó hoạt động bằng cách sử dụng phản ánh để lấy một Parse(String)
phương pháp tĩnh từ đối số kiểu chung chung và gọi phương pháp đó cho chuỗi được thông qua tại tôi đã xây dựng nó như là một phương pháp mở rộng để cho phép bạn để làm công cụ như thế này:.
var intValue = "1234".TryParse<Int32>();
var doubleValue = "1234".TryParse<Double>();
Thật không may điều này sẽ không hoạt động trên enums
vì chúng không có chữ ký giống nhau cho phương pháp phân tích cú pháp, do đó bạn không thể sử dụng tiện ích này để phân tích cú pháp số enum
. tạo ra một trường hợp đặc biệt cho enums.
Một trong những điều tốt đẹp về cách tiếp cận này là chi phí truy xuất phương pháp Parse
thông qua phản ánh chỉ phát sinh khi sử dụng lần đầu tiên do đại biểu tĩnh được tạo cho tất cả các lần sử dụng tiếp theo.
Một điều nữa - điều duy nhất gây khó chịu về cách tiếp cận này là không có phần mở rộng ngôn ngữ hoặc đường cú pháp giúp việc này trở nên dễ dàng. Những gì tôi đã hy vọng đạt được với mã này là ít hơn cách clunky của việc sử dụng các phương pháp tiêu chuẩn TryParse
tồn tại trong BCL.
Cá nhân tôi thấy mô hình này khá xấu xí:
Int32 value;
if (Int32.TryParse(someString, out value))
// do something with value
chủ yếu là bởi vì nó đòi hỏi một khai báo biến trước thời hạn và việc sử dụng một tham số out
. Cách tiếp cận của tôi ở trên không phải là thực sự là tốt hơn nhiều:
var result = someString.TryParse<Int32>();
if (result.Item1)
// do something with result.Item2
gì sẽ thực sự mát mẻ sẽ được nhìn thấy một phần mở rộng ngôn ngữ C# được xây dựng để làm việc với một Tuple<Boolean, T?>
mà sẽ cho phép chúng tôi làm việc với loại hình này suôn sẻ nhưng Tôi có cảm giác tôi càng viết về điều này rằng nó không thực sự có vẻ khả thi.
Giả sử điều này thực sự hoạt động, 1: P –
Xét mục đích chính cho sự tồn tại của 'TryParse' không ném một ngoại lệ trên thất bại, "cách tiếp cận tốt hơn" của bạn đã hoàn tác nhằm mục đích tồn tại của nó: http: //www.codinghorror.com/blog/archives/000358.html –
@ 280z28 - Đủ công bằng nhưng ngoại lệ tôi ném là khác nhau. Ngoại lệ này được ném ra khi bạn cố gắng phân tích một kiểu không có phương thức 'TryParse (String)' mà không bao giờ xảy ra khi bạn gọi phương thức 'TryParse' bình thường. Ngoại lệ này chắc chắn sẽ được phát hiện bởi các nhà phát triển trong thử nghiệm và sẽ không xảy ra trong thời gian chạy vì vậy nó không chính xác giống như ngoại lệ sẽ được che giấu bởi một thất bại phân tích cú pháp. –