问题 尝试从WinJS中读取C#WinRT组件中的空字符串时出现异常


我有以下情况: C#中的数据库编译为Windows运行时组件。

其中一个类看起来像这样:

public sealed class MyData
{
  string TheGoods { get; private set;}
}

用户界面在WinJS中,我有以下内容:

var b = dataInstance.theGoods;

问题是我得到一个异常,属性中包含以下内容:

System.ArgumentNullException    at System.StubHelpers.HStringMarshaler.ConvertToNative(String managed)

看一下HStringMarshaler.ConvertToNative的实现,如果字符串为null,它似乎抛出。

这是否意味着将空字符串暴露给WinJS是不可能的?这是WinJS限制还是适用于所有WinRT?

虽然string.Empty确实有效,但它在语义上与null不同,在某些情况下,empty是有效的且不同于null。

如果我将属性的类型更改为'object',那么它确实有效,但是当它确实应该是一个字符串时暴露一个对象似乎很讨厌。 有任何想法吗?文档对此非常清楚


12538
2017-10-19 19:13


起源



答案:


Windows运行时字符串类型是值类型,没有空值。由于这个原因,.NET投影禁止在Windows运行时ABI边界上传递空的.NET字符串。

Windows运行时使用的字符串类型是 HSTRING 类型。虽然此类型没有null值,但它确实为null 表示 (也就是说,在C ++中, HSTRING s = nullptr; 已验证)。一个 HSTRING 使用null表示是一个空字符串。

.NET投影将此null表示转换为空字符串(String.Empty)对于从ABI边界进入的字符串,并禁止实际的空.NET字符串通过ABI边界传回。


13
2017-10-19 19:26



那么对于C#,可以安全地说类构造函数应该将字符串初始化为string.Empty吗?如果更新文档提及它会很好。 msdn.microsoft.com/en-us/library/windows/apps/... - Oren Novotny
嗯,这取决于。 .NET字符串类型仍然是引用类型,可以为null。只有在跨越ABI边界传递字符串时才允许使用null(即,当.NET字符串转换为Windows运行时HSTRING时)。因此,也许仍然存在空字符串有用的情况,您只需要确保在跨越ABI边界之前检查字符串。 - James McNellis
正确...因此对于那些直接或通过接口返回WinRT的类型,字符串应该初始化为空。谢谢! - Oren Novotny


答案:


Windows运行时字符串类型是值类型,没有空值。由于这个原因,.NET投影禁止在Windows运行时ABI边界上传递空的.NET字符串。

Windows运行时使用的字符串类型是 HSTRING 类型。虽然此类型没有null值,但它确实为null 表示 (也就是说,在C ++中, HSTRING s = nullptr; 已验证)。一个 HSTRING 使用null表示是一个空字符串。

.NET投影将此null表示转换为空字符串(String.Empty)对于从ABI边界进入的字符串,并禁止实际的空.NET字符串通过ABI边界传回。


13
2017-10-19 19:26



那么对于C#,可以安全地说类构造函数应该将字符串初始化为string.Empty吗?如果更新文档提及它会很好。 msdn.microsoft.com/en-us/library/windows/apps/... - Oren Novotny
嗯,这取决于。 .NET字符串类型仍然是引用类型,可以为null。只有在跨越ABI边界传递字符串时才允许使用null(即,当.NET字符串转换为Windows运行时HSTRING时)。因此,也许仍然存在空字符串有用的情况,您只需要确保在跨越ABI边界之前检查字符串。 - James McNellis
正确...因此对于那些直接或通过接口返回WinRT的类型,字符串应该初始化为空。谢谢! - Oren Novotny