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. 演算子を作成できると仮定すると、「?」を使用できますか?ブール値の標準のTernaryOpで使用されている場合でも、列挙の演算子として?
  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にコンパイルしてからJITする方法について多くのことを学ぶことができます。

また、構文では、字句ストリームをはるかに先読みして、三項演算子と新しい演算子のどちらを見ているのかを判断する必要があることにも注意してください。

于 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ユーティリティのバインドが確実に解除され、かなり新しいコードファイル拡張子のためにほとんど最初から書き直したくないことに注意してください。新しい言語..

しかし、待ってください、もっとあり、それははるかに簡単です!

.blarghファイルクラスも必要ありません。プロジェクト構造は、MSBuildビルドシステムに基づいてビルドされます。ドライブのどこかに、「ソリューションビルド」または「プロジェクトビルド」中にビルドシステムが実行するすべてのステップを説明する一連のXMLスクリプトがあります。それらは編集可能であり、さらに優れており、拡張可能です。プラグインをビルドシステムに記述し、ビルドプロセスの実質的にすべての既存のステップの間にプラグインを挿入することができます。

単純さを想像してみてください。追加のマークアップを含むC#ファイルをロードして処理し、通常のC#に変換された「展開」を書き戻す単純な検索置換ユーティリティを作成します。「コンパイル」フェーズの前にそれを注入することができ、問題は完了です。

覚えておくべきことの1つは、元のファイルを上書きすることはできないということです。それは賢明ではありません。それは、あなたがあなたの新しい演算子で簡単に書いたものすべてが自動拡張され、ビルド時に永久に置き換えられることを意味するからです。:)拡張されたファイルを一時ファイルに書き込み、そのファイルをビルド中の現在の一時コンパイルファイルセットに追加します(また、元のファイルは不要になったため、削除します)。

これも、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 に答える