我试图创建一个通用扩展,使用'TryParse'来检查字符串是否为给定类型:

public static bool Is<T>(this string input)
{
    T notUsed;
    return T.TryParse(input, out notUsed);
}

这将无法编译,因为它无法解析符号TryParse

据我所知,“TryParse”不是任何接口的一部分。

这有可能吗?

更新:

使用以下我想出的答案:

public static bool Is<T>(this string input)
{
    try
    {
        TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(input);
    }
    catch
    {
        return false;
    }

    return true;
}

它工作得很好,但我认为以这种方式使用异常对我来说不合适。

更新2:

修改为传递类型而不是使用泛型:

public static bool Is(this string input, Type targetType)
{
    try
    {
        TypeDescriptor.GetConverter(targetType).ConvertFromString(input);
        return true;
    }
    catch
    {
        return false;
    }
}

当前回答

使用try/catch进行流控制是一种糟糕的策略。抛出异常会导致运行时在处理异常时性能滞后。相反,在转换之前验证数据。

var attemptedValue = "asdfasdsd";
var type = typeof(int);
var converter = TypeDescriptor.GetConverter(type);
if (converter != null &&  converter.IsValid(attemptedValue))
    return converter.ConvertFromString(attemptedValue);
else
    return Activator.CreateInstance(type);

其他回答

这是一个“一般约束”的问题。因为你没有一个特定的界面,那么你就会陷入困境,除非你遵循前面的建议。

有关这方面的文档,请查看以下链接:

http://msdn.microsoft.com/en-us/library/ms379564 (VS.80) . aspx

它向您展示了如何使用这些约束,并应该为您提供更多的线索。

你不能在一般类型上这样做。

您可以创建一个接口ITryParsable,并将其用于实现该接口的自定义类型。

我猜你打算将它用于基本类型,如int和DateTime。您不能更改这些类型来实现新的接口。

当我想做几乎完全相同的事情时,我必须以艰难的方式实现它,考虑到反思。给定T,考虑typeof(T)并寻找TryParse或Parse方法,如果找到了就调用它。

我最近还需要一个通用的TryParse。这是我想到的;

public static T? TryParse<T>(string value, TryParseHandler<T> handler) where T : struct
{
    if (String.IsNullOrEmpty(value))
        return null;
    T result;
    if (handler(value, out result))
        return result;
    Trace.TraceWarning("Invalid value '{0}'", value);
    return null;
}

public delegate bool TryParseHandler<T>(string value, out T result);

那么这就是一个简单的调用问题:

var value = TryParse<int>("123", int.TryParse);
var value2 = TryParse<decimal>("123.123", decimal.TryParse);

你应该使用TypeDescriptor类:

public static T Convert<T>(this string input)
{
    try
    {
        var converter = TypeDescriptor.GetConverter(typeof(T));
        if(converter != null)
        {
            // Cast ConvertFromString(string text) : object to (T)
            return (T)converter.ConvertFromString(input);
        }
        return default(T);
    }
    catch (NotSupportedException)
    {
        return default(T);
    }
}