You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Standard 1.6中TypeConverter替代方案及类型转换异常处理

Alright, let's work through this problem—since TypeConverter isn't available in .NET Standard 1.6, we need solid alternatives to replace try/catch for checking if a string can be converted to your generic type T in the GetData<T> method. Here are a few practical approaches you can implement:

1. Explicit TryParse Checks for Common Value Types

For basic value types like int, bool, DateTime, etc., you can directly check the type of T and call the corresponding TryParse method. This is straightforward and avoids reflection overhead.

internal static T GetData<T>(string input, T defaultValue)
{
    // Handle int conversions
    if (typeof(T) == typeof(int))
    {
        if (int.TryParse(input, out int result))
            return (T)(object)result;
    }
    // Handle bool conversions
    else if (typeof(T) == typeof(bool))
    {
        if (bool.TryParse(input, out bool result))
            return (T)(object)result;
    }
    // Add other common types as needed: long, double, DateTime, Guid, etc.
    else if (typeof(T) == typeof(DateTime))
    {
        if (DateTime.TryParse(input, out DateTime result))
            return (T)(object)result;
    }

    // Fallback if conversion fails or type isn't explicitly handled
    return defaultValue;
}

Pros: Fast, no reflection overhead, easy to debug.
Cons: Requires manual updates to support new types—you'll need to add an else if block for every type you want to handle.

2. Reflectively Invoke TryParse (Automatic Support for Compatible Types)

If you want to automatically support any type that has a static TryParse(string, out T) method (which most built-in value types do), you can use reflection to locate and call this method. This avoids manually coding each type.

internal static T GetData<T>(string input, T defaultValue)
{
    // Look for a static TryParse method with the signature: bool TryParse(string, out T)
    var tryParseMethod = typeof(T).GetMethod(
        "TryParse",
        new[] { typeof(string), typeof(T).MakeByRefType() }
    );

    if (tryParseMethod != null)
    {
        object[] parameters = new object[] { input, null };
        bool conversionSuccess = (bool)tryParseMethod.Invoke(null, parameters);
        
        if (conversionSuccess)
        {
            return (T)parameters[1];
        }
    }

    // Handle enums separately (since Enum.TryParse is on the Enum class, not the enum type itself)
    if (typeof(T).IsEnum)
    {
        if (Enum.TryParse(input, out T enumResult))
        {
            return enumResult;
        }
    }

    // Fallback for unsupported types or failed conversions
    return defaultValue;
}

Pros: Automatically supports any type with a matching TryParse method; no manual type additions needed.
Cons: Minor reflection overhead (though this is negligible for most use cases, and still cheaper than catching exceptions on failure paths).

3. Custom Convertible Interface for Complex/Custom Types

If you need to support custom types that don't have a TryParse method, create a dedicated interface for string-to-type conversion. This gives you full control over how custom types are converted.

First, define the interface:

public interface IStringConvertible<T>
{
    bool TryConvertFromString(string input, out T result);
}

Then implement it in your custom type:

public class UserId : IStringConvertible<UserId>
{
    public int Value { get; private set; }

    private UserId(int value) => Value = value;

    public bool TryConvertFromString(string input, out UserId result)
    {
        result = null;
        if (int.TryParse(input, out int intValue) && intValue > 0)
        {
            result = new UserId(intValue);
            return true;
        }
        return false;
    }
}

Update your GetData<T> method to check for this interface:

internal static T GetData<T>(string input, T defaultValue)
{
    // First check for TryParse as in approach 2
    var tryParseMethod = typeof(T).GetMethod(
        "TryParse",
        new[] { typeof(string), typeof(T).MakeByRefType() }
    );

    if (tryParseMethod != null)
    {
        object[] parameters = new object[] { input, null };
        bool conversionSuccess = (bool)tryParseMethod.Invoke(null, parameters);
        
        if (conversionSuccess)
        {
            return (T)parameters[1];
        }
    }

    // Handle enums
    if (typeof(T).IsEnum)
    {
        if (Enum.TryParse(input, out T enumResult))
        {
            return enumResult;
        }
    }

    // Check for custom convertible interface
    var convertibleInterface = typeof(IStringConvertible<>).MakeGenericType(typeof(T));
    if (convertibleInterface.IsAssignableFrom(typeof(T)))
    {
        var convertMethod = convertibleInterface.GetMethod("TryConvertFromString");
        if (convertMethod != null)
        {
            object[] parameters = new object[] { input, null };
            bool conversionSuccess = (bool)convertMethod.Invoke(null, parameters);
            
            if (conversionSuccess)
            {
                return (T)parameters[1];
            }
        }
    }

    return defaultValue;
}

Pros: Full control over custom type conversions; clean, extensible pattern.
Cons: Requires modifying custom types to implement the interface.

Final Notes

Choose the approach that best fits your use case:

  • Use approach 1 if you only need to support a small, fixed set of basic types.
  • Use approach 2 for broad support of built-in types without manual coding.
  • Use approach 3 alongside the others if you need to handle custom complex types.

All these methods avoid relying on try/catch for conversion checks, which is more performant and cleaner than exception-based logic for expected failure cases.

内容的提问来源于stack exchange,提问作者Parsa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:25:00