C# には拡張プロパティがありますか?
-
03-07-2019 - |
質問
C# には拡張プロパティがありますか?
たとえば、拡張プロパティを追加できますか? DateTimeFormatInfo
呼ばれた ShortDateLongTimeFormat
どちらが戻ってくるか ShortDatePattern + " " + LongTimePattern
?
解決
いいえ、C#3.0には存在せず、4.0では追加されません。 C#に必要な機能のリストにあるため、将来追加される可能性があります。
この時点でできることは、GetXXXスタイルの拡張メソッドです。
他のヒント
いいえ、存在しません。
私は、C#チームが一時的に(または少なくともEric Lippertがそうであった)それらを考慮していたことを知っています-拡張機能のコンストラクターと演算子(これらは頭を動かすのに時間がかかるかもしれませんが...) 、C#4の一部になるという証拠は見ていません。
編集:C#5には表示されませんでした。2014年7月の時点では、C#6にも表示されません。
Eric Lippert は、2012年11月までMicrosoftのC#コンパイラチームの主任開発者であり、 2009年10月:
当面は、Roslynコンパイラーによってそのまま使用できる状態ではまだサポートされていません...
今まで、拡張プロパティは、C#標準の以前のバージョンに含めるほど価値があるとは見なされていませんでした。 C#7 と C#8.0 はこれを提案のチャンピオンと見なしましたが、まだリリースされていませんでした。何よりも、既に実装があったとしても、それを作りたいからです。最初からすぐに。
しかし... ...
拡張メンバー アイテムが< strong> C#7ワークリスト 。近い将来サポートされる可能性があります。 。拡張プロパティの現在のステータスは、 Githubの関連アイテムで確認できます。
>ただし、&quot; extend everything&quot;というさらに有望なトピックがあります特にプロパティと静的クラス、さらにはフィールドに焦点を当てています。
さらに回避策を使用できます
この記事で指定されているように、実行時にオブジェクトインスタンスに属性を付加する TypeDescriptor
機能。ただし、標準プロパティの構文は使用していません。
単なる構文糖とは少し異なり、拡張メソッド
string GetData()のエイリアスとして
はデータをクラスに保存するためです。
string Data(this MyClass instance)
のような拡張プロパティを定義する可能性を追加します。このMyClassインスタンス)
C#7がすべての機能拡張(プロパティとフィールド)を提供することを願っていますが、その時点では時間だけがわかります。
そして、明日のソフトウェアはコミュニティから来るので、気軽に貢献してください。
更新:2016年8月
dotnetチームが公開した C#7.0の新機能および Mads Torgensen :
拡張プロパティ:(すばらしい!)インターンを実装しました 実験としての夏、およびその他の種類の拡張 メンバー。私たちは引き続きこれに興味を持っていますが、それは大きな変化であり、 価値があると確信する必要があります。
拡張プロパティと他のメンバーは、Roslynの将来のリリースに含まれるのにまだ良い候補のようですが、7.0のものではないかもしれません。
更新:2017年5月
拡張メンバー は、 拡張機能のすべての問題 もクローズされています。 主な議論は、実際には広義のタイプの拡張性についてでした。 この機能は ここで提案 で追跡され、 7.0マイルストーン 。
更新:2017年8月-C#8.0で提案された機能
まだ提案された機能のみですが、構文はどうなるのかがより明確になりました。これがneになることを覚えておいてください
アップデート(おかげさまで) @カオスト このアップデートについてご指摘いただきました):
マッツ・トルガーセン: 「拡張機能はすべて C# 8.0 に組み込まれませんでした。この言語は、言語のさらなる将来についての非常に刺激的な議論に「巻き込まれた」と言えるでしょう。私たちは、将来の可能性を阻害する形でこの言語を追加しないようにしたいと考えています。言語設計は時には非常に長いゲームになることがあります!」
ソース: コメントセクションの https://blogs.msdn.microsoft.com/dotnet/2018/11/12/building-c-8-0/
私は、これが実装されることを期待してこの質問を開いたのは何年もの間、何度数えることをやめました。
さあ、ついにみんなで喜ぶことができます!Microsoft は、今後の C# 8 リリースでこれを導入する予定です。
したがって、これを行う代わりに...
public static class IntExtensions
{
public static bool Even(this int value)
{
return value % 2 == 0;
}
}
ようやくこんな風にできるようになりますよ…
public extension IntExtension extends int
{
public bool Even => this % 2 == 0;
}
ソース: https://blog.ndepend.com/c-8-0-features-glimpse-future/
@Psyonityで述べたように、conditionalWeakTableを使用して、既存のオブジェクトにプロパティを追加できます。動的なExpandoObjectと組み合わせて、動的な拡張プロパティを数行で実装できます。
using System.Dynamic;
using System.Runtime.CompilerServices;
namespace ExtensionProperties
{
/// <summary>
/// Dynamically associates properies to a random object instance
/// </summary>
/// <example>
/// var jan = new Person("Jan");
///
/// jan.Age = 24; // regular property of the person object;
/// jan.DynamicProperties().NumberOfDrinkingBuddies = 27; // not originally scoped to the person object;
///
/// if (jan.Age < jan.DynamicProperties().NumberOfDrinkingBuddies)
/// Console.WriteLine("Jan drinks too much");
/// </example>
/// <remarks>
/// If you get 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create' you should reference Microsoft.CSharp
/// </remarks>
public static class ObjectExtensions
{
///<summary>Stores extended data for objects</summary>
private static ConditionalWeakTable<object, object> extendedData = new ConditionalWeakTable<object, object>();
/// <summary>
/// Gets a dynamic collection of properties associated with an object instance,
/// with a lifetime scoped to the lifetime of the object
/// </summary>
/// <param name="obj">The object the properties are associated with</param>
/// <returns>A dynamic collection of properties associated with an object instance.</returns>
public static dynamic DynamicProperties(this object obj) => extendedData.GetValue(obj, _ => new ExpandoObject());
}
}
使用例はxmlコメントにあります:
var jan = new Person("Jan");
jan.Age = 24; // regular property of the person object;
jan.DynamicProperties().NumberOfDrinkingBuddies = 27; // not originally scoped to the person object;
if (jan.Age < jan.DynamicProperties().NumberOfDrinkingBuddies)
{
Console.WriteLine("Jan drinks too much");
}
jan = null; // NumberOfDrinkingBuddies will also be erased during garbage collection
最近これが必要になったので、答えのソースを見てみました:
さらに動的なバージョンを作成しました:
public static class ObjectExtenders
{
static readonly ConditionalWeakTable<object, List<stringObject>> Flags = new ConditionalWeakTable<object, List<stringObject>>();
public static string GetFlags(this object objectItem, string key)
{
return Flags.GetOrCreateValue(objectItem).Single(x => x.Key == key).Value;
}
public static void SetFlags(this object objectItem, string key, string value)
{
if (Flags.GetOrCreateValue(objectItem).Any(x => x.Key == key))
{
Flags.GetOrCreateValue(objectItem).Single(x => x.Key == key).Value = value;
}
else
{
Flags.GetOrCreateValue(objectItem).Add(new stringObject()
{
Key = key,
Value = value
});
}
}
class stringObject
{
public string Key;
public string Value;
}
}
おそらく大幅に改善できます(名前付け、文字列ではなく動的)、現在はCF 3.5でこれをハックConditionalWeakTable( https://gist.github.com/Jan-WillemdeBruyn/db79dd6fdef7b9845e217958db98c4d4 )