gpt4 book ai didi

c# - 没有异常风险的通用类型转换

转载 作者:太空狗 更新时间:2023-10-29 19:56:34 24 4
gpt4 key购买 nike

我正在开发一个可以采用多种不同数据类型(任何实现 IComparable 的数据类型)的控件。

我需要能够将这些与传入的另一个变量进行比较。

如果主要数据类型是 DateTime,并且传递给我的是 String,我需要

  • 尝试将字符串转换为日期时间以执行日期比较。
  • 如果无法将字符串转换为 DateTime,则进行字符串比较。

所以我需要一种通用的方法来尝试从任何类型转换为任何类型。很简单,.Net 为我们提供了 TypeConverter类。

现在,要确定 String 是否可以转换为 DateTime,我能做的最好的事情就是使用异常。如果 ConvertFrom 引发异常,我知道我不能进行转换并且必须进行字符串比较。

以下是我得到的最好的:

        string theString = "99/12/2009";
DateTime theDate = new DateTime ( 2009, 11, 1 );

IComparable obj1 = theString as IComparable;
IComparable obj2 = theDate as IComparable;

try
{
TypeConverter converter = TypeDescriptor.GetConverter ( obj2.GetType () );
if ( converter.CanConvertFrom ( obj1.GetType () ) )
{
Console.WriteLine ( obj2.CompareTo ( converter.ConvertFrom ( obj1 ) ) );
Console.WriteLine ( "Date comparison" );
}
}
catch ( FormatException )
{
Console.WriteLine ( obj1.ToString ().CompareTo ( obj2.ToString () ) );
Console.WriteLine ( "String comparison" );
}

我们的部分工作标准规定:

只有在出现异常情况时才应引发异常 - 即。遇到错误。

但这并不是特例。我需要另一种解决方法。

大多数变量类型都有一个 TryParse方法返回一个 bool 值,以允许您确定转换是否成功。但是 TypeConverter 没有可用的 TryConvert 方法。 CanConvertFrom如果可以在这些类型之间进行转换并且不考虑要转换的实际数据,则只进行 dermines。 IsValid方法也没有用。

有什么想法吗?

编辑

我不能使用 AS 和 IS。我在编译时不知道这两种数据类型。所以我不知道该怎么做!!!

编辑

确定了那个 SCSS 。它不像 Marc Gravells 那样整洁,但它确实有效(我希望如此)。感谢马克的灵感。我会在有空的时候整理它,但我有一些错误修复需要继续处理。

    public static class CleanConverter
{
/// <summary>
/// Stores the cache of all types that can be converted to all types.
/// </summary>
private static Dictionary<Type, Dictionary<Type, ConversionCache>> _Types = new Dictionary<Type, Dictionary<Type, ConversionCache>> ();

/// <summary>
/// Try parsing.
/// </summary>
/// <param name="s"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool TryParse ( IComparable s, ref IComparable value )
{
// First get the cached conversion method.
Dictionary<Type, ConversionCache> type1Cache = null;
ConversionCache type2Cache = null;

if ( !_Types.ContainsKey ( s.GetType () ) )
{
type1Cache = new Dictionary<Type, ConversionCache> ();

_Types.Add ( s.GetType (), type1Cache );
}
else
{
type1Cache = _Types[s.GetType ()];
}

if ( !type1Cache.ContainsKey ( value.GetType () ) )
{
// We havent converted this type before, so create a new conversion
type2Cache = new ConversionCache ( s.GetType (), value.GetType () );

// Add to the cache
type1Cache.Add ( value.GetType (), type2Cache );
}
else
{
type2Cache = type1Cache[value.GetType ()];
}

// Attempt the parse
return type2Cache.TryParse ( s, ref value );
}

/// <summary>
/// Stores the method to convert from Type1 to Type2
/// </summary>
internal class ConversionCache
{
internal bool TryParse ( IComparable s, ref IComparable value )
{
if ( this._Method != null )
{
// Invoke the cached TryParse method.
object[] parameters = new object[] { s, value };
bool result = (bool)this._Method.Invoke ( null, parameters);

if ( result )
value = parameters[1] as IComparable;

return result;
}
else
return false;

}

private MethodInfo _Method;
internal ConversionCache ( Type type1, Type type2 )
{
// Use reflection to get the TryParse method from it.
this._Method = type2.GetMethod ( "TryParse", new Type[] { type1, type2.MakeByRefType () } );
}
}
}

最佳答案

泛型是一种选择吗?这是一个厚颜无耻的黑客攻击 TryParse 方法并通过(缓存的)委托(delegate)调用它:

using System;
using System.Reflection;

static class Program
{
static void Main()
{
int i; float f; decimal d;
if (Test.TryParse("123", out i)) {
Console.WriteLine(i);
}
if (Test.TryParse("123.45", out f)) {
Console.WriteLine(f);
}
if (Test.TryParse("123.4567", out d)) {
Console.WriteLine(d);
}
}
}
public static class Test
{
public static bool TryParse<T>(string s, out T value) {
return Cache<T>.TryParse(s, out value);
}
internal static class Cache<T> {
public static bool TryParse(string s, out T value)
{
return func(s, out value);
}
delegate bool TryPattern(string s, out T value);
private static readonly TryPattern func;
static Cache()
{
MethodInfo method = typeof(T).GetMethod(
"TryParse", new Type[] { typeof(string), typeof(T).MakeByRefType() });
if (method == null) {
if (typeof(T) == typeof(string))
func = delegate(string x, out T y) { y = (T)(object)x; return true; };
else
func = delegate(string x, out T y) { y = default(T); return false; };
} else {
func = (TryPattern) Delegate.CreateDelegate(typeof(TryPattern),method);
}
}
}
}

关于c# - 没有异常风险的通用类型转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2111280/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com