1

我最近发现自己想知道是否存在类似于三元运算符的现有运算符,但用于枚举......这可能是一个处理工具,用于编写更少的代码来处理枚举的值......

我找不到任何东西,所以我提出了这个问题......

如何构建自己的运算符来处理枚举,如下所述?

进行以下枚举:

public enum ComTypes { Call, Email, SMS } 

假设我需要根据 ComType 分配弹出对话框的标题。目前我可以像这样使用三元运算符:

ComTypes comType = ...;
var title = comType == ComTypes.Call ? "Make a Call" : 
    comType == ComTypes.Email ? "Send an Email" : 
    /* ComTypes.SMS */ "Send a Text";

我想要的是使用新的枚举运算符获得更简洁的格式......类似于以下内容:

ComTypes comType = ...;
var title = comType ? 
    .Call: "Make a Call", 
    .Email: "Send an Email", 
    .SMS|default: "Send a Text";

所以我想我的入门问题是:

  1. 我可以创建自定义运算符并将其与普通 C# 编译器并行使用吗?
  2. 假设我可以创建运算符,我可以使用“?” 作为枚举的运算符,即使它被标准的三元运算用于布尔值?
  3. 我知道我可以去谷歌搜索这个,但如果有人对好的编译器创建文章有任何建议,那就太好了。

- 编辑 -

我只是想把它放在这里...我知道如果这阻止我进行开发是不切实际的...我知道如何通过其他几种方式实现...我想要的是一些帮助了解我实现我所概述的目标的起点......仅仅是为了尝试编写代码并了解更多关于我日常使用的框架的乐趣。

4

5 回答 5

3

你为什么不想使用只是开关?

string title = "";

switch (comType)
{
  case (ComTypes.Call):
    title = "Make a Call";
    break;
  case (ComTypes.Email):
    title = "Send an Email";
    break; 
  case (ComTypes.SMS):
    title = "Send a Text";
    break;
}
于 2012-08-14T00:28:56.710 回答
2

根据您对其他答案的评论,您似乎希望将此作为学习练习,而不是您将在生产代码中使用的东西,因此虽然我会为任何其他情况推荐几个非常好的答案,但这里是您可以通过自定义编译器执行以下几种方法:

  • 编写一个运行预构建的应用程序,它会扫描所有 C# 文件以查找自定义语法,并在将其输入编译器之前将其替换为 switch 语句。
  • 使用内置的自定义语法编写您自己的完整 C# 编译器。(.NET C# 编译器不是开源的 AFAIK)
  • 修改Mono 的编译器以包含您的新语法。这可能是最简单的解决方案,您仍然会学到很多关于如何将 C# 编译为 CIL 然后 JITted。

另请注意,您的语法要求您在词法流中查看非常远的内容,以确定您是在查看三元运算符还是新运算符。

于 2012-08-14T00:51:59.223 回答
2

好的,至于如何:我无法给您任何确切的答案,但是按照您所说的方式,这种情况几乎是不可能的。

CODE 编译器是完全.. 嗯.. 密封的。它是单片的,带有一些小的扩展点(请参阅 ExtensionMethods 和 LINQ 子语言)。如果你真的找到了 LINQ 子语言插件是如何附加到编译器的,请给我留言,我很高兴。我对此表示怀疑,我相信 LINQ 语法是硬编码到编译器中的,但也许我错了。

但是,如果我没记错的话——那么添加一个运算符是完全不可能的,至少在你查看它的方式上是这样。当然还有其他方法。

查看 XAML 或 ASPX 文件,或 RESX?编译器如何处理它们,嗯?构建项目是一个多步骤的过程。解析 XAML/ASPX/RESX 文件是在 C# 代码编译之前。读取该文件,工具生成 .g.cs /.Designer.cs /aspx.cs/.resx.cs 文件,然后将这些文件添加到编译集中,而 XAML/ASPX/RESX 实际上并未由 C# 编译编译器。

这是什么意思?这意味着您可以将文件的扩展名更改为例如 .blargh,然后编写像 XAML/ASPX/RESX 解析器/生成器这样的插件来将 .blargh 预处理为 .cs,然后瞧。在 .blargh 中,您有自己的额外语法好东西,翻译成冗长的 C#,然后由普通 C# 编译器编译。

但请注意,虽然它实际上会很好地工作,但更改文件扩展名肯定会解除 Intellisense 和其他 csharpy IDE 实用程序的绑定,而且我敢打赌,你不想几乎从头开始重写它们以获得漂亮的新代码文件扩展名 - 实际上,漂亮新语言..

但是等等,还有更多,而且更简单!

您甚至不需要 .blagh 文件类。项目结构建立在 MSBuild 构建系统之上。在你的驱动器上的某个地方有一堆 XML 脚本,它们描述了构建系统在“解决方案构建”或“项目构建”期间所做的每一个步骤。它们是可编辑的,甚至更好的是,它们是可扩展的。您可以将插件写入构建系统,并将其注入到构建过程的几乎任何现有步骤之间。

想象一下简单性:您编写了一个简单的搜索替换实用程序,它使用您的额外标记加载一个 C# 文件,对其进行处理,然后写回“扩展的”,翻译成普通的 C#。你可以在“编译”阶段之前注入它,你就完成了你的问题。

要记住的一件事:您不能覆盖原始文件。这是不明智的,因为这意味着您使用新操作员简要编写的所有内容 - 将在构建时自动扩展和替换 - 永久。:) 您将希望将扩展后的文件写入某个临时文件,将该文件添加到 build 下的当前临时编译文件集(并删除原始文件,因为不再需要它)。

您应该注意到,这正是 XAML/RESX/.. 文件和 .g.cs/.resx.cs/... 临时文件所发生的情况。这是因为这是在 VS/MSBuild 系统中处理此类情况的正常方式 :) 如果您不想构建新的语言支持,您可以在您的语言和一些已知语言之间进行翻译,然后将其添加为预处理步骤。就这样。

于 2012-08-14T00:56:07.020 回答
1

在我看来,您想将枚举用作哈希表。为什么不直接使用哈希表。

Dictionary<ComTypes,String>
于 2012-08-14T00:32:03.120 回答
0

三元运算符不是 C# 中的可重载运算符。

话虽如此,我会推荐简洁的:

public enum ComTypes { Call = 0, Email = 1, SMS = 2 };
public readonly string[] ComTitles = 
     { "Make a Call", "Send an Email", "Send a Text" };

稍后在代码中你可以使用

ComTitles[comType]
于 2012-08-14T00:41:30.710 回答