C# 如何确定是否可以在不使用异常的情况下将值分配给DataTable列 问题

C# 如何确定是否可以在不使用异常的情况下将值分配给DataTable列 问题,c#,exception-handling,datatable,C#,Exception Handling,Datatable,你好!我想知道是否有可能编写这种C代码: 不使用例外。我的用例是处理大量的行(1000+),我知道这种情况会经常发生,所以我希望避免异常处理的开销以提高性能。那么,有没有可能像使用字典一样检查这个问题 bool isAssignable = SomeMagicDataHelper.TrySetValue(dataColumn, someStringValue); if (!isAssignable) { // Now I know, that the value is not appli

你好!我想知道是否有可能编写这种C代码:

不使用例外。我的用例是处理大量的行(1000+),我知道这种情况会经常发生,所以我希望避免异常处理的开销以提高性能。那么,有没有可能像使用字典一样检查这个问题

bool isAssignable = SomeMagicDataHelper.TrySetValue(dataColumn, someStringValue);
if (!isAssignable)
{
    // Now I know, that the value is not applicable to the type
}
我知道这可以通过反射来实现,但我想这样的解决方案甚至比异常方法还要慢


谢谢

我将编写一个扩展方法,检查该类型是否为有效的datacolumn类型:

public static bool IsValidType<T>(this DataColumn col, T someStringValue)
{
  return col.Datatype == typeof(T);
}

我想我应该这样做。它的核心思想是,列可以是有限的类型列表。大多数都提供了
TryParse
,其他(
string
byte[]
)更简单。但是,由于不能通过接口调用static
TryParse
方法,并且通过反射调用它有点难看和缓慢,因此我决定将其编写为生成不同语句的模板。这使它保持快速,并允许您编写一个可维护的模板,而不是一个庞大的代码文件

将其保存在
.tt
()文件中:


使用制度;
使用系统数据;
名称空间MyApp
{
公共静态类SomeMagicDataHelper
{
公共静态bool TrySetValue(DataRow DataRow、DataColumn DataColumn、object value)
{
尝试
{
如果(值==null)
{
如果(!dataColumn.AllowDBNull)
返回false;
其他的
{
dataRow[dataColumn]=DBNull.Value;
返回true;
}
}
//如果类型完全匹配,则直接赋值将起作用
if(value.GetType()==dataColumn.DataType)
{
dataRow[dataColumn]=值;
返回true;
}
//否则,我们会做一个锥虫
开关(dataColumn.DataType.FullName)
{
案例“”:
dataRow[dataColumn]=值;
返回true;
案例“”:
返回false;
案例“”:
{
tryValue;
如果(.TryParse(value.ToString(),out tryValue))
{
dataRow[dataColumn]=tryValue;
返回true;
}
其他的
{
返回false;
}
}
}
//最后,可能抛出异常
dataRow[dataColumn]=值;
返回true;
}
捕获(例外情况除外)
{
//log ex,这不应该是一件普通的事情
返回false;
}
}
}
}

我也想到了这样的事情。。。只是希望有某种内置的方法来实现它:-)我最终采用了这种方法,它比总是捕获
参数异常
(相同的过程60秒->3秒)要快得多。非常感谢:-)问题是它只适用于类型完全匹配的列和值。我想提前知道的是,对于int列,值“4”是有效的,“4”不是您所说的“提前知道”的意思。您何时需要知道?我正在填充我的
DataTable
s的数据是作为文件中的字符串值提供的,我正在动态创建和填充这些表。如果一个值应该分配给一个无效的列,我想在实际分配给单元格之前知道它,这样就不需要异常处理
public static bool IsValidType<T>(this DataColumn col, T someStringValue)
{
  return col.Datatype == typeof(T);
}
if (column.IsValidType(someStringValue)
{
  dataRow[dataColumn] = someStringValue    
}
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ output extension=".cs" #>
using System;
using System.Data;

namespace MyApp
{
    public static class SomeMagicDataHelper
    {
        public static bool TrySetValue(DataRow dataRow, DataColumn dataColumn, object value)
        {
            try
            {
                if (value == null)
                {
                    if (!dataColumn.AllowDBNull)
                        return false;
                    else
                    {
                        dataRow[dataColumn] = DBNull.Value;
                        return true;
                    }
                }
                // if the types match exactly, a direct assignment will work
                if (value.GetType() == dataColumn.DataType)
                {
                    dataRow[dataColumn] = value;
                    return true;
                }
                // otherwise, we'll do a TryParse
                switch (dataColumn.DataType.FullName)
                {
                    case "<#= typeof(string).FullName #>":
                        dataRow[dataColumn] = value;
                        return true;
                    case "<#= typeof(byte[]).FullName #>":
                        return false;
<# foreach (var type in new[] { typeof(Boolean), typeof(Byte), typeof(Char), typeof(DateTime), typeof(Decimal), typeof(Double), typeof(Guid), typeof(Int16), typeof(Int32), typeof(Int64), typeof(SByte), typeof(Single), typeof(TimeSpan), typeof(UInt16), typeof(UInt32), typeof(UInt64) }) {
#>                    case "<#= type.FullName #>":
                    {
                        <#= type.Name #> tryValue;
                        if (<#= type.Name #>.TryParse(value.ToString(), out tryValue))
                        {
                            dataRow[dataColumn] = tryValue;
                            return true;
                        }
                        else
                        {
                            return false;
                        }
                    }
<# } #>
                }

                // last resort, might throw an exception
                dataRow[dataColumn] = value;
                return true;
            }
            catch (Exception ex)
            {
                // log ex, this shouldn't be a common thing
                return false;
            }
        }
    }
}