C#:“漂亮”类型 名称 功能?
对于泛型类型,System.Type 类的名称属性会返回一个奇怪的结果。有没有办法以更接近我指定的方式获取类型名称?
示例:typeof(List
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
对于泛型类型,System.Type 类的名称属性会返回一个奇怪的结果。有没有办法以更接近我指定的方式获取类型名称?
示例:typeof(List
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(13)
“漂亮”名称的问题在于它们根据您使用的语言而有所不同。想象一下,如果
OriginalName
返回 C# 语法,VB.NET 开发人员会感到多么惊讶。但是,您自己制作它相当容易:
这将递归地解析非托管名称,因此,如果您有类似
Dictionary>
的内容,它应该仍然可以工作。The problem with "pretty" names is they are different depending on the language you are using. Imagine the surprise of a VB.NET developer if
OriginalName
returned C# syntax.However, it's pretty fairly easy to make this yourself:
This will recursively resolve the unmanaged name, so that if you have something like
Dictionary<string, IList<string>>
it should still work.我使用
CodeDomProvider
转换为 c#:I used
CodeDomProvider
to convert to c#:就像 Harold Hoyer 的答案,但包括可空值和一些其他内置类型:
Like Harold Hoyer's answer but including nullables and a few more built-in types:
这是我的实现。它是为了描述方法而创建的,因此它可以处理
ref
和out
关键字。调用代码如下所示:
其中
method
是MethodInfo
实例。需要注意的是:我不需要描述任何多维数组类型,因此我没有费心实现描述,但通过调用 type.GetArrayRank() 来添加会相当容易代码>.
Here is my implementation. It was created to describe methods, so it handles the
ref
andout
keywords.The calling code looks like this:
Where
method
is aMethodInfo
instance.One note: I didn't have a need to describe any multi-dimensional array types, so I didn't bother implementing description for that, but it would be fairly easy to add by calling
type.GetArrayRank()
.利用
CodeDomProvider
的最小工作解决方案是首先控制CodeTypeReference
实例的构建方式。仅针对泛型类型和多等级数组有特殊情况,因此我们只需要关心这些:使用此修改后的工厂方法,然后可以使用适当的代码提供程序来获得漂亮的输入,如下所示:
上面的代码返回 IObservable, string>>>[,]。唯一处理不好的特殊情况是 Nullable 类型,但这实际上更多是 CodeDomProvider 的错误。
A minimal work solution that leverages
CodeDomProvider
is to control how theCodeTypeReference
instance is built in the first place. There are special cases only for generic types and multi-rank arrays, so we only have to care about those:Using this modified factory method, it is then possible to use the appropriate code provider to get pretty typing, like so:
The above code returns
IObservable<IEnumerable<Tuple<Nullable<int>, string>>>[,]
. The only special case that is not handled well areNullable
types but this is really more a fault of theCodeDomProvider
than anything else.你必须自己写这个。请记住,
Type.Name
等正在调用 CLR 中的方法,并且可以从多种语言调用。这就是为什么它们看起来不像 C# 或 VB 或调用者编码所用的语言,而是看起来像 CLR 表示形式。进一步注意,
string
以及其他类型的别名是诸如System.String
之类的 CLR 类型的别名。同样,这会影响您所看到的格式。使用反射并不难,但我质疑它的价值。
You have to write this yourself. Keep in mind that
Type.Name
etc. are invoking methods that live in the CLR and can be invoked from multiple languages. This is why they don't come back looking like C# or VB or the language the caller was coded in, but instead looking like the CLR representation.Note further that
string
and what not are aliases for CLR types likeSystem.String
. Again, this plays a role in the formatting that you see.It's not hard to do using reflection, but I question the value of it.
第一:感谢纳维德避免重新发明轮子。如果可以的话我会投票。
如果有人走这条路(至少对于 VS10/.Net 4),这里有几点需要补充:[\w\.]+)>";
* 尝试将 CodeTypeReference 的变体之一与类型参数一起使用。这避免了使用字符串类型名称(例如尾随 &)的许多陷阱,并且意味着您将返回
bool
而不是System.Boolean
等。像这样的许多类型的完整命名空间,但您可以稍后删除命名空间部分。* 简单的 Nullables 往往以
System.Nullable
的形式返回,而不是int?
- 您可以使用答案上的正则表达式转换为更好的语法,例如:<代码>const string NullablePattern = @"System.Nullable<(?
const string NullableReplacement = @"${nulledType}?";
答案 = Regex.Replace(answer, NullablePattern, NullableReplacement);
* 像
out T?
这样的方法参数的类型给出了一个非常不透明的字符串。如果有人有一种优雅的方式来处理这样的事情,我很想知道。希望这一切在罗斯林的帮助下变得非常容易。
First: Kudos to Navid for wheel reinvention avoidance. I would upvote if I could.
Here are a few points to add, if anyone goes down this path (at least for VS10/.Net 4):
* Try using one of the variants of CodeTypeReference with Type arguments. This avoids a number of pitfalls of using string type names (such as trailing &) and means you get back
bool
instead ofSystem.Boolean
etc. You do get back the full namespace for a lot of types like this but you can always get rid of the namespace part later.* Simple Nullables tend to come back in the form
System.Nullable<int>
rather thanint?
- You can convert to the nicer syntax with a regex on the answer such as:const string NullablePattern = @"System.Nullable<(?<nulledType>[\w\.]+)>";
const string NullableReplacement = @"${nulledType}?";
answer = Regex.Replace(answer, NullablePattern, NullableReplacement);
* The Type of a method argument like
out T?
gives a very opaque string. If anyone has an elegant way of dealing with things like this I would love to know about it.Hopefully this all becomes very easy with Roslyn.
结合了一些答案,添加了对嵌套类型和数组等级的支持,并将其转变为具有缓存解析名称的扩展方法。
Combined a few answers, added support for nested types and array ranks, and turned it into an extension method with cached resolved names.
正如您的示例中所示,您可以期待该类型,因此您可以尝试一下
as in your example you can expect the type so you can try that
我知道您想比较类型。
做到这一点的最好方法是...
myVar 是 List
或myVar.GetType() == myOtherVar.GetType()
如果您不需要这个...请忽略我的回答。
I understand that you want to compare types.
The best way to do this is...
myVar is List<string>
ormyVar.GetType() == myOtherVar.GetType()
If you don't need this... please disregard my answer.
我明白了,我必须自己写这个。这是我的解决方案(实际上比要求的要多一些)。这可能是有帮助的。
I understood, that I have to write this myself. Here is my solution (it is actually a bit more than asked for). It is, probably, helpfull.
我这样做..
如果您不希望每次都递归地解析泛型类型参数中的类型,则应定义
PREVENT_RECURSION
true
,只需从缓存中获取字典;如果你不关心的话,请将其保留为未定义的 false 。I do it like this ..
where
PREVENT_RECURSION
should be definedtrue
if you don't want the type in generic type arguments be resolved recursively every time, just take from the cache dictionary; leave it undefined of false if you don't care that.我的两分钱:
My two cents: