简体   繁体   English

如何在 C# 中为内置类型设置别名?

[英]How to alias a built-in type in C#?

So in C++, I'm used to being able to do:所以在 C++ 中,我习惯于能够做到:

typedef int PeerId;

This allows me to make a type more self-documenting, but additionally also allows me to make PeerId represent a different type at any time without changing all of the code.这使我可以使类型更具自文档性,而且还允许我随时使 PeerId 表示不同的类型,而无需更改所有代码。 I could even turn PeerId into a class if I wanted.如果我愿意,我什至可以将 PeerId 变成一个类。 This kind of extensibility is what I want to have in C#, however I am having trouble figuring out how to create an alias for 'int' in C#.这种可扩展性是我想要在 C# 中拥有的,但是我无法弄清楚如何在 C# 中为“int”创建别名。

I think I can use the using statement, but it only has scope in the current file I believe, so that won't work (The alias needs to be accessible between multiple files without being redefined).我想我可以使用 using 语句,但它只在我相信的当前文件中具有范围,因此不起作用(别名需要在多个文件之间可以访问而无需重新定义)。 I also can't derive a class from built-in types (but normally this is what I would do to alias ref-types, such as List or Dictionary).我也无法从内置类型派生类(但通常这是我对引用类型的别名所做的事情,例如列表或字典)。 I'm not sure what I can do.我不确定我能做什么。 Any ideas?有任何想法吗?

您需要使用完整的类型名称,如下所示:

using DWORD = System.Int32;

Summary 摘要

Here's the short answer: 这是简短的回答:

  • Typedefs are actually a variable used by compile-time code generators. Typedef实际上是编译时代码生成器使用的变量。
  • C# is being designed to avoid adding code generation language constructs. C#旨在避免添加代码生成语言结构。

Therefore, the concept of typedefs doesn't fit in well with the C# language. 因此,typedef的概念不适合C#语言。

Long Answer 答案很长

In C++, it makes more sense: C++ started off as a precompiler that spit out C code, which was then compiled. 在C ++中,它更有意义:C ++最初是作为一个预编译器,它吐出C代码,然后编译。 This "code generator" beginning still has effects in modern C++ features (ie, templates are essentially a Turing-complete language for generating classes and functions at compile time). 这个“代码生成器”开始仍然具有现代C ++特性的效果(即,模板本质上是用于在编译时生成类和函数的图灵完备语言)。 In this context, a typedef makes sense because it's a way to get the "result" of a compile-time type factory or "algorithm" that "returns" a type. 在这种情况下,typedef是有意义的,因为它是获取编译时类型工厂的“结果”或“返回”类型的“算法”的一种方法。

In this strange meta-language (which few outside of Boost have mastered), a typedef is actually a variable. 在这种奇怪的元语言中(Boost之外很少有人掌握),typedef实际上是一个变量。

What you're describing is less complex, but you're still trying to use the typedef as a variable. 您所描述的内容不那么复杂,但您仍在尝试将typedef用作变量。 In this case, it's used as an input variable. 在这种情况下,它用作输入变量。 So when other code uses the typedef, it's really not using that type directly. 因此,当其他代码使用typedef时,它实际上并没有直接使用该类型。 Rather, it's acting as a compile-time code generator, building classes and methods based on typedef'ed input variables. 相反,它充当编译时代码生成器,基于typedef的输入变量构建类和方法。 Even if you ignore C++ templates and just look at C typedefs, the effect is the same. 即使您忽略C ++模板并只看C typedef,效果也是一样的。

C++ and Generative Programming C ++和生成编程

C++ was designed to be a multi-paradign language (OO and procedural, but not functional until Boost came out). C ++被设计成一种多范式语言(OO和程序,但在Boost问世之前不起作用)。 Interestingly enough, templates have evolved an unexpected paradign: generative programming. 有趣的是,模板已经发展出一种意想不到的范式:生成性编程。 (Generative programming was around before C++, but C++ made it popular). (生成式编程在C ++之前就已存在,但C ++使它很受欢迎)。 Generative programs are actually meta-programs that - when compiled - generate the needed classes and methods, which are in turn compiled into executables. 生成程序实际上是元程序 - 在编译时 - 生成所需的类和方法,这些类和方法又被编译成可执行文件。

C# and Generative Programming C#和生成编程

Our tools are slowly evolving in the same direction. 我们的工具正朝着同一个方向缓慢发展。 Of course, reflection emit can be used for "manual" generative programming, but it is quite painful. 当然,反射发射可以用于“手动”生成编程,但是非常痛苦。 The way LINQ providers use expression trees is very generative in nature. LINQ提供程序使用表达式树的方式本质上非常具有生成性。 T4 templates get really close but still fall short. T4模板非常接近,但仍然不足。 The "compiler as a service" which will hopefully be part of C# vNext appears most promising of all, if it could be combined with some kind of type variable (such as a typedef). 如果它可以与某种类型的变量(例如typedef)结合使用,那么希望成为C#vNext一部分的“编译器即服务”似乎最有希望。

This one piece of the puzzle is still missing : generative programs need some sort of automatic trigger mechanism (in C++, this is handled by implicit template instantiation ). 这个难题的一部分仍然缺失 :生成程序需要某种自动触发机制(在C ++中,这由隐式模板实例化处理)。

However, it is explicitly not a goal of C# to have any kind of "code generator" in the C# language like C++ templates (probably for the sake of understandability; very few C++ programmers understand C++ templates). 但是,在C#语言中使用任何类型的“代码生成器”(如C ++模板)可能明显不是 C#的目标(可能为了可理解性;很少有C ++程序员理解C ++模板)。 This will probably be a niche satisfied by T4 rather than C#. 这可能是T4而不是C#所满足的利基。

Conclusion (repeating the Summary) 结论(重复摘要)

All of the above is to say this: 所有这些都是这样说的:

  • Typedefs are a variable used by code generators. Typedef是代码生成器使用的变量。
  • C# is being designed to avoid adding code generation language constructs. C#旨在避免添加代码生成语言结构。

Therefore, the concept of typedefs doesn't fit in well with the C# language. 因此,typedef的概念不适合C#语言。

You could (ab)use implicit conversions: 你可以(ab)使用隐式转换:

struct PeerId
{
    private int peer;

    public static implicit operator PeerId(int i)
    {
        return new PeerId {peer=i};
    }

    public static implicit operator int(PeerId p)
    {
        return p.peer;
    }
}

This takes the same space as an int, and you can do: 这与int占用相同的空间,您可以这样做:

PeerId p = 3;
int i = p;

But I agree you probably don't need this. 但我同意你可能不需要这个。

I also sometimes feel I need (integer) typedefs for similar purposes to the OP. 我有时也觉得我需要(整数)typedef用于与OP类似的目的。

If you do not mind the casts being explicit (I actually want them to be) you can do this: 如果你不介意演员是明确的(我实际上希望他们),你可以这样做:

enum PeerId : int {};

Will also work for byte, sbyte, short, ushort, uint, long, or ulong (obviously). 也适用于byte, sbyte, short, ushort, uint, long,ulong (显然)。

Not exactly the intended usage of enum , but it does work. 不完全是enum的预期用法,但它确实有效。

Redefining fundamental types just for the sake of changing the name is C++ think and does not sit well with the more pure Object Orientated C#. 为了更改名称而重新定义基本类型是C ++认为并且不适合更纯粹的面向对象的C#。 Whenever you get the urge to shoehorn a concept from one language into another, you must stop and think whether or not it makes sense and try to stay native to the platform. 每当你想要将一种概念从一种语言转换为另一种语言时,你必须停下来思考它是否有意义,并尝试保持原生于平台。

The requirement of being able to change the underlying type easily can be satisfied by defining your own value type. 通过定义自己的值类型,可以满足能够轻松更改基础类型的要求。 Coupled with implicit conversion operators and arithmetic operators, you have the power to define very powerful types. 与隐式转换运算符和算术运算符相结合,您可以定义非常强大的类型。 If you are worried about performance for adding layers on top of simple types, don't. 如果您担心在简单类型之上添加图层的性能,请不要。 99% chance that it won't, and the 1% chance is that in case it does, it will not the be "low hanging fruit" of performance optimization. 99%的可能性它不会,1%的可能性是,如果确实如此,它将不会是性能优化的“低悬的果实”。

Since C# 10 you can use:从 C# 10 开始,您可以使用:

global using PeerId = System.Int32;

It works for all files.它适用于所有文件。

It should appear before all using directives without the global modifier.它应该出现在所有没有全局修饰符的 using 指令之前。

See using directive .请参阅using 指令

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM