LoginSignup
5
1

More than 5 years have passed since last update.

今更a == 1 && a == 2 && a == 3の話

Last updated at Posted at 2018-08-31

はじめに

if(a == 1 && a == 2 && a == 3)を常にtrueにしたい、という話が結構前にありました。
Can (a== 1 && a ==2 && a==3) ever evaluate to true?

これをC#で推奨されない方法で解決してみたいと思います。

問題の整理

さて、この問題ですべきことを見てみましょう。

  • if(a == 1 && a == 2 && a == 3)を常にtrueにしたい

まあ単純な話で、副作用を持つプロパティを使用すればいいのでは……と思いきや、単純にその方法で実装してしまっては、次のようなコードにおいて、問題文の条件を達成できません。

if(a == 1 && a == 2 && a == 3)
{
    //何らかの処理
}
if(a == 1 && a == 2 && a == 3)
{
    //ここを通らない
}

問題で与えられているのは、if(a == 1 && a == 2 && a == 3)常にtrueにすることです。

問題解決への道筋

ということで今回は、以下のようなコードで条件を達成することを考えます。

code.cs
using System;
namespace MyNamespace
{
    class MyClass
    {
        static void Main()
        {
            var a = 1;

            if(a == 1 && a == 2 && a == 3)
            {
                Console.WriteLine("Hello, world!");
            }
            if (a == 1 && a == 2 && a == 3)
            {
                Console.WriteLine("Hello, myself!");
            }
        }
    }
}

演算子オーバーロードと文脈キーワード

文脈キーワード

文脈キーワードとは、特定の文脈でのみキーワードとなるキーワードのことです(正確には、contextual keywordといいます)。
たとえば、C#においてyieldは単独ではキーワードではありません。
ですが、後ろにbreakreturnがつくと、yield breakyield returnという一つのキーワードとして動作するようになります。

さて、ご存知の通り、C#においてvarは文脈キーワードです。
以下のコードがコンパイル可能なことからもわかるでしょう。

VarVariable.cs
namespace MyNamespace
{
    class VarVariable
    {
        object var;
    }
}

これはvarという名前のフィールドを宣言しています。
そして、以下のコードもコンパイル可能です。

VarClass.cs
namespace MyNamespace
{
    class VarClass
    {
        class var
        {
        }

        static void Main()
        {
            var var;
        }
    }
}

わかりにくいのですが、Main()にあるvarの型は型推論を行うためのvarではなく、VarClassで定義された型としてのclassのvarです。

暗黙の型変換

さて、見かけ上何もしていない風に見せかけたいので、var型の変数var1を代入したいのですが、当然1はそのままでは数値なので代入できません。
そのため、暗黙の型変換を定義します。

VarClass-2.cs
namespace MyNamespace
{
    class VarClass
    {
        class var
        {
            public static implicit operator var(int i) => new var();
        }

        static void Main()
        {
            var a = 1;
        }
    }
}

これでvar型の変数aに、1が型変換されて入るようになります。

等価のオーバーロード

次に、a数値の==での比較をtrueにする方法を考えましょう。
これは単純で、==演算子をオーバーロードするだけでOKです。が、!=演算子もオーバーロードする必要があります。

(抜粋)VarClass-3.cs
class var
{
    public static implicit operator var(int i) => new var();

    public static bool operator ==(var v, int i) => true;

    public static bool operator !=(var v, int i) => false;
}

これで左辺にvar型、右辺にint型が来たときの==の動作を定義することができました。
最後にvar.classを隠蔽するためにvar.classを別ファイルに分けてあげれば完成です。

注釈

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1