1. ホーム
  2. c#

[解決済み】C#には拡張プロパティがある?

2022-03-23 22:14:07

質問

C#には拡張プロパティがありますか?

例えば、拡張プロパティを DateTimeFormatInfo という ShortDateLongTimeFormat を返します。 ShortDatePattern + " " + LongTimePattern ?

解決方法は?

今のところ、Roslynコンパイラーではまだサポートされていません ...

これまで、拡張プロパティは、以前のバージョンのC#標準に含まれるほど価値のあるものとは見なされていませんでした。 C# 7 C# 8.0 というのも、すでに実装があったとしても、最初からきちんとしたものを作りたいというのが一番の理由です。

でも、それは ...

があります。 拡張メンバー の項目は C# 7作業リスト ということで、近い将来サポートされるかもしれません。拡張プロパティの現在の状況は、以下のサイトで確認できます。 Githubの関連項目 .

しかし、さらに有望なトピックがあります。 エクステンド・エブリシング" 特にプロパティと静的クラス、あるいはフィールドに焦点を当てます。

さらに、次のような回避策もあります。

で指定されているように 記事 を使用することができます。 TypeDescriptor 機能を使用すると、実行時にオブジェクトのインスタンスに属性を付けることができます。ただし、標準的なプロパティの構文を使っているわけではありません。

のような拡張プロパティを定義する可能性を追加した、単なる構文上の糖分とは少し違う。

string Data(this MyClass instance) 拡張メソッドのエイリアスとして

string GetData(this MyClass instance) は、データをクラスに格納するためです。

C#7では、すべての機能(プロパティとフィールド)を備えた拡張機能が提供されることを期待していますが、その点については、時間が経ってみないとわかりません。

そして、明日のソフトウェアはコミュニティから生まれるので、自由に貢献してください。

更新日:2016年8月

dotnetチームが公開したように C# 7.0での新機能 のコメントから マッズ・トルゲンセン :

エクステンションプロパティ:インターン生に実装してもらいました。 他の種類の拡張機能とともに、実験として夏に行われました。 メンバーです。しかし、これは大きな変化であり、私たちはまだこの問題に関心を持ち続けています。 その価値があるという確信が必要です。

拡張プロパティやその他のメンバーは、まだRoslynの将来のリリースに含まれる良い候補のようですが、7.0のものではないのかもしれません。

更新日:2017年5月

エクステンションメンバー と重複しているため、閉鎖しました。 エクステンション・エブリシング・イシュー こちらも終了しました。 主な議論は、実際には、広い意味でのTypeの拡張性についてでした。 この機能は現在、追跡されています 提案としてこちら から削除され 7.0マイルストーン .

2017年8月更新】C# 8.0提案機能

に過ぎないままですが 提案された 機能ですが、その構文がより明確になりました。これは、拡張メソッドの新しい構文にもなることを覚えておいてください。

public interface IEmployee 
{
    public decimal Salary { get; set; }
}

public class Employee
{
    public decimal Salary { get; set; }
}

public extension MyPersonExtension extends Person : IEmployee
{
    private static readonly ConditionalWeakTable<Person, Employee> _employees = 
        new ConditionalWeakTable<Person, Employee>();


    public decimal Salary
    {
        get 
        {
            // `this` is the instance of Person
            return _employees.GetOrCreate(this).Salary; 
        }
        set 
        {
            Employee employee = null;
            if (!_employees.TryGetValue(this, out employee)
            {
                employee = _employees.GetOrCreate(this);
            }
            employee.Salary = value;
        }
    }
}

IEmployee person = new Person();
var salary = person.Salary;

部分クラスと似ていますが、別のクラス/タイプとして別のアセンブリにコンパイルされます。この方法では、静的メンバや演算子を追加することができます。で述べたように マッズ・トルゲンセンのポッドキャスト , この場合、拡張モジュールは状態を持たないので (つまりクラスにプライベートなインスタンスメンバを追加できません)、 インスタンスにリンクしたプライベートなインスタンスデータを追加することはできません。 . その理由は、内部で辞書を管理することになり、メモリ管理などが大変になるためです。 このような場合にも TypeDescriptor / ConditionalWeakTable のテクニックを使い、プロパティの拡張で、素敵なプロパティの下に隠します。

構文は変更される可能性があります。 問題 . 例えば extends は次のように置き換えることができます。 for この方がより自然で、Javaとの関連性が薄いと感じる人もいるかもしれません。

2018年12月更新 ロール、エクステンション、静的インターフェースメンバー

エクステンションのすべて はC# 8.0には採用されませんでした。この記事の最後にあるように、いくつかの欠点があるためです。 GitHubチケット . そこで、設計を改善するための模索が行われました。 ここで マッズ・トルゲンセンは、以下のように説明しています。 ロールとエクステンション とその違いについて説明します。

ロールは、ある特定の値に対してインターフェースを実装することを可能にします。 型になります。拡張機能により、ある型のすべての値に対してインターフェイスを実装することができます。 特定のコード領域内で、与えられた型を使用します。

これまでの提案を2つのユースケースに分割して見ることができる。その 拡張のための新しい構文 はこのようになります。

public extension ULongEnumerable of ulong
{
    public IEnumerator<byte> GetEnumerator()
    {
        for (int i = sizeof(ulong); i > 0; i--)
        {
            yield return unchecked((byte)(this >> (i-1)*8));
        }
    }
}

とすると、こんな感じになります。

foreach (byte b in 0x_3A_9E_F1_C5_DA_F7_30_16ul)
{
    WriteLine($"{e.Current:X}");
}

そして 静的インターフェース :

public interface IMonoid<T> where T : IMonoid<T>
{
    static T operator +(T t1, T t2);
    static T Zero { get; }
}

を追加します。 拡張プロパティ について int を処理し int として IMonoid<int> :

public extension IntMonoid of int : IMonoid<int>
{
    public static int Zero => 0;
}