C#最佳将动态类型转换为字符串的方法

64
以下代码从DataTable获取一个字段并将其转换为字符串。 有没有更简洁的方法将dynamic类型转换为字符串?
```html

以下代码从DataTable获取一个字段并将其转换为字符串。 有没有更简洁的方法将dynamic类型转换为字符串?

```
dynamic value = dataTable.Rows[i].Field<dynamic>(columnName);
value = (value == null) ? null : value.ToString();
5个回答

114
string value = Convert.ToString(dataTable.Rows[i][columnName]);

标准格式化将启动,无需使用泛型、扩展方法或动态。


1
这难道不是更简单吗?不需要转换,对吧?这样可以吗?string value = dataTable.Rows[i][columnName]; - cr1pto
@cloud 只有在它已经是字符串的情况下才能工作。转换不关心它是什么。 - Marc Gravell
因此,在处理动态内容时,我们应该始终使用转换以确保安全,还是这取决于具体情况? - cr1pto
1
相反地,我会说通常没有必要使用动态语言,而且它会给你带来很多麻烦。@cloudsteifebro - Marc Gravell

21

首先,正如Marc在他的回答中提到的那样,“标准格式将启动,不需要使用泛型、扩展方法或动态”,因此在您的情况下,您不必使用dynamic关键字,您可以直接转换为字符串,但是谈到从动态类型转换为字符串,我有两种方法:

第一种方式

string x = Convert.ToString(value) // value is a dynamic object
优点:如果您不确定编译后的数据类型是否支持转换为字符串,或者它是硬编码的(例如 int),则这是一种很好的转换方式。 缺点:如果您尝试在 扩展方法 中执行 Convert.ToString(value) // value is a dynamic object,则此方法可能会导致错误。当我这样做时,会出现以下错误:"Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax"
因此,如果您例如正在使用 Asp.Net Core 的 HttpContext.Session.SetString(),并且您将 Convert.ToString(value) // value is dynamic object 作为内联转换放置在参数中,则会在缺点部分出现错误。要解决此问题,您可以在函数参数外部分配一个变量来存储 Convert.ToString(value) 的结果,然后将该变量发送到扩展函数参数中。
dynamic value = 10;
HttpContext.Session.SetString("key",Convert.ToString(value));  <-- error

解决:

dynamic value = 10;
string x = Convert.ToString(value);
HttpContext.Session.SetString("key",x);  // works fine

或者使用第二种方式(强制转换),确保编译后的数据类型支持转换为字符串

HttpContext.Session.SetString("key",(string)value);

第二种方法
如果编译后的数据类型支持,cast dynamicstring

string x = (string)value;  //value is dynamic object

优点: - 如果您想在扩展方法参数内进行内联转换,则非常有用 - 如果您想确保编译数据类型支持转换为string并基于此生成异常,也很有用
缺点:这不能适用于所有数据类型,因此如果您想要更通用的转换方法,则建议使用第一种方式。

MS文档中所述:“动态类型使其出现的操作可以绕过编译时类型检查。相反,这些操作在运行时解决。”

因此,dynamic变量的数据类型在运行时编译,并且采用的类型不同于dynamic,如果解释的对象支持,则可以使用casting或使用Convert.ToString()进行更通用的类型转换。

附注:如果要转换为字符串以外的数据类型,则可能会面临数据丢失,例如将浮点数转换为整数,因此请注意。


2
虽然这可能回答了问题,但需要一些解释。请更新问题并解释一下为什么这个解决方案能够起作用。 - Brett DeWoody
2
不能保证字段的值是字符串,因此 OP 正在询问如何将其转换为字符串。您的代码仅在对象实际上是字符串时才有效,而接受的答案只要 Convert.ToString 可以处理它就可以工作,这更有可能发生。请注意,例如,如果基础值是 int,则会出现运行时错误 RuntimeBinderException:"无法将类型 'int' 转换为 'string'"。 - Lasse V. Karlsen
@LasseVågsætherKarlsen 实际上_casting_是一种转换方式,可以处理一些在C#中不被视为字符串的数据类型,比如NewtonsoftJObject,你可以通过_casting_将json字符串中的数字数据转换为字符串,并且谁说他想保证字段的值是一个字符串,也许他想在它不是字符串时抛出异常。 - Mawardy
昨天更新了VisualStudio之后,我能够做到这一点: var listOfInts = new List<int>(); var x = listOfInts.Select(i => Convert.ToString(i)); - Felipe Andrés Ramírez Darvich
我发现这个解释非常有用。由于我使用Xamarin开发应用程序,当链接器行为设置为SDK Only时,总是会出现这种重载字符串错误。也许Xamarin无法从动态中读取字符串,因此将(string)dy_obj.var放入代码中可以使其正常工作,而不是使用Convert.ToString(dy_obj.var) - Mr Hery

1

我有一个情况,其中动态内容应该是一个字符串,但在错误情况下是一个数字(我调用的代码无法更改正在执行这个操作)。

在我的情况下,我执行以下操作:

string x = value as string;
if (x == null)
{
   // error condition
} else {
   //use x here
}

我认为最好使用 is 关键字,例如 if (x is null) { ... } - TERIHAX

0
如果你确定从你的动态变量提供一个字符串。下面是一个函数的示例,我在其中控制一个值是否为空或不为空的动态变量。
private void AddIfNotNull(List <dynamic> list, dynamic item) 
    {
       string value = item?.value?.ToString();
    
       if (!string.IsNullOrEmpty(value)) 
         list.Add(item);
    }

希望能有所帮助。

-2

Convert.ToString 对我来说不起作用,因为我的数据是 double[][],结果会是 "System.Double[][]"。

double[,] figure_geometry = new double[2, 2] { { 1.0, 1.0 }, { 2.0, 2.0 } };
string geometry = JsonSerializer.Serialize(figure_geometry);

运行良好


这个回答如何回答这个问题?“有没有更简洁的方法从DataTabledynamic转换为string?” - Enigmativity
它直接回答。这是最干净的转换方式,因为其他建议可能在某些情况下产生不良结果。 - Danil
这个问题是关于如何从DataTable中将dynamic类型的引用转换为string,而你介绍了一个叫做figure.geometry的东西,并且使用JsonSerializer将其转换为一个叫做markerDto.geometry的东西?你还说你正在将double[][]转换为double[][]?唯一共同点就是单词“convert”。请删除此答案。 - Enigmativity
问题是“如何将动态转换为字符串”。与DataTable无关。您可以拥有任何类型的数据,并非所有数据都可以通过Convert.ToString进行转换。 - Danil
请再次阅读问题。它特别提到了“DataTable”,并且有这段代码:dataTable.Rows[i].Field<dynamic>(columnName)。您的代码将double[,]转换为string。这不是同一件事。 - Enigmativity
是的,抱歉,我现在明白了double[,]转换为stringdynamic转换为string是一样的。 DataTable只是一个谎言。 - Enigmativity

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接