19

または、次のことが不可能なのはなぜですか。

class Material
{
    class Keys
    {
        ...
    }

    Material.Keys Keys { get; set; } // Illegal
}

あいまいさの可能性はありません。インスタンスからアクセスする場合は、プロパティを返します。静的にアクセスする場合は、クラスを返します。それとも私は何かが足りないのですか?

私は「修正」を求めているのではありませんが(MaterialKeysなどのように別の名前を付けることができることはわかっています)、この制限の背後にある技術的な理由があります。

4

5 に答える 5

17

しかし、あなたがこれを持っていたと想像してください:

class Material
{
    class Keys
    {
        ...
    }

    static Material.Keys Keys = new Keys();
}

現在、両方が「静的」スコープにあります。さて、コンパイラはすべてのケースであいまいさを解消できますか? そうでなければ、これは許されません。

インスタンスメンバーではなく、静的フィールド/プロパティ/メソッドに対して曖昧さ回避が機能する可能性があると思います。またはその逆です。その場合、言語仕様で、インスタンス メンバーが内部クラスと同じ名前を持つことを許可し、静的には許可しないようにしますか? それはただ混乱するでしょう。

しかし、メンバーを内部クラスの名前と一致させることは、とにかくかなり混乱します。

于 2011-01-19T03:16:02.550 に答える
15

「あいまいでないものはすべて合法であるべきだ」というのは、C# 言語の設計原則ではありません。C# 言語は、"質の低い" 言語になるように設計されています。つまり、言語の規則により、明らかに正しいコードでいっぱいの穴にあなたを投げ込む必要があり、その穴から抜け出して、それを間違ったコードに変えなければなりません。「あいまいでないものはすべて合法であるべきだ」という考えは、ほとんどの場合、「品質の落とし穴」言語の概念に真っ向から反するものです。

さらに、機能を実行しないことの正当な理由を提供する必要があるというあなたの考えは逆です。機能を実行しない理由を提供する必要はありませ。むしろ、提案された機能は、その利点が莫大なコストを上回ることを実証することによって正当化されなければなりません. 機能は非常に高価であり、予算も限られています。お客様に利益をもたらすために、最高の機能のみを実行する必要があります。

提案された機能により、脆弱で紛らわしいコードを簡単に作成できます。これは、C# を「品質の穴」言語ではなく「絶望の穴」言語にするのに役立ちます。言語に脆弱性と混乱を加える機能は、それらのコストを補うために莫大な利益を追加する必要があります。この機能がそのコストを正当化する言語に追加する大きな利点は何だと思いますか?

答えが「そのような利点はありません」である場合、言語にその機能がない理由がわかりました。それは、言語を悪化させるからです。

利点がある場合は、言語の仮想的な将来のバージョンでのメリットを喜んで検討します。

于 2011-01-19T07:11:27.307 に答える
4

あなたが言った、

インスタンスでアクセスすると、プロパティを返します。静的にアクセスする場合は、クラスを返します。

Keysしかし、どこかだけで と言うとどうなりますかMaterial? これは静的アクセスですか、それともインスタンス アクセスですか? これはプロパティKeysまたはネストされた型を参照していますかKeys? それは実際にはあいまいです。

例えば、

class Material
{
    class Keys
    {
        public static int Length;
    }

    string Keys { get; set; }

    public void Process()
    {
        // Does this refer to string.Length (via property Keys)
        // or Material.Keys.Length? It actually refers to both.
        Console.WriteLine(Keys.Length);
    }
}

コメントで指摘されているように、これがすべてではありません。しかし、ほとんど。Color次のタイプの名前のプロパティを持つことは有効でColorあり、衝突はありません。

public Color Color { get; set; }

Color.FromName(...)   // refers to static method on the type ‘Color’
Color.ToString()      // refers to instance method on the property’s value

しかし、現在のスコープ内のものはより外側のスコープのものに勝つため、これは簡単に解決できます。

public class MyType { public string FromName(string name) { return null; } }
public MyType Color;

Color.FromName(...)   // unambiguously refers to MyType::FromName(string)
                      // via the property Color

あなたの例ではそれほど簡単ではありません — ネストされたクラスKeysとプロパティKeysは同じスコープにあります (同じ宣言型を持っています)。どちらを優先するかはどうやって決めるのですか?そのうちの 1 つを優先することにしたとしても、同じ名前のものは 2 つしか持つことができず、1 つが静的で、もう 1 つがインスタンスでなければならないため、これはほとんど役に立ちません。

于 2011-01-19T02:52:34.927 に答える
3

私の答えは、他の質問とは少し異なる視点から質問にアプローチします。C#言語仕様の次の2つのステートメントのうち:

The same identifier may not be used in different definitions within one scope

The same identifier may not be used in different definitions within one scope, unless it is probably impossible for any ambiguity to arise when the identifier is used

、最初の方がはるかに簡単です。

単純さは言語設計の重要な目標です。言語が単純であると、コンパイラーとインタープリターの作成者が実装しやすくなり、ツールの生成と操作が容易になり、初心者が習得しやすくなり、プログラマーが理解しやすくなるためです。言語機能を検討するとき、その機能が言語に追加する複雑さはネガティブと見なされるべきであり、したがって、少なくとも同等の有用性の尺度によってバランスをとる必要があります。あなた自身が述べたように、これを許可しても実際の機能は追加されないため(回避するのが非常に簡単であるため)、C#仕様を含めることでさらに複雑にする理由はありませんでした。

于 2011-01-19T04:27:15.927 に答える
2

ネストされたクラスKeysはのメンバーであるためMaterial、プロパティはそのままKeysです。という 2 人のメンバーがいKeysます。

同じように、同じものと呼ばれる 2 つのプロパティを持つことはできません。

public class Bar
{
    private bool Foo { get; set; }
    private string Foo { get; set; }
}

アクセスFooしようとしているのはどれですか?

public class Material : Keys
{

    private Keys K { get; set; }
}

public class Keys
{

}

正常に動作しますが、おそらくあなたが求めているものではありません。

于 2011-01-19T02:49:10.867 に答える