C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

EnumからDictionaryを作る拡張メソッド

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■90595 / inTopicNo.1)  EnumからDictionaryを作る拡張メソッド
  
□投稿者/ yoshi (1回)-(2019/03/23(Sat) 08:20:45)

分類:[VB.NET/VB2005 以降] 

環境:VB2017、.Net4.72
Enumの名前をキーとするDictionaryを作る拡張メソッドを以下のように作りました。

 <System.Runtime.CompilerServices.Extension()>
    Public Function ToDictionary(Of T)(type As Type) As Dictionary(Of String, T)
        Return [Enum].GetValues(type).Cast(Of T)().
            ToDictionary(Function(x) x.ToString(), Function(x) x)
    End Function

この書き方では呼び出し側で次のようになります。
 Dim dic = GetType(DayOfWeek).ToDictionary(Of DayOfWeek)

2回DayOfWeekをコーディングするのは、めんどくさいので拡張メソッド側を変更して
次のように書きたいのですが可能でしょうか?

Dim dic = GetType(DayOfWeek).ToDictionary
もしくは
Dim dic =[Enum].ToDictionary(GetType(DayOfWeek))

引用返信 編集キー/
■90596 / inTopicNo.2)  Re[1]: EnumからDictionaryを作る拡張メソッド
□投稿者/ Hongliang (773回)-(2019/03/23(Sat) 11:06:14)
拡張メソッドにする意義が分かりません。
Public Function EnumToDictionary(Of T)() As Dictionary(Of String, T)
と言う関数をモジュールに定義すれば十分ではないでしょうか。
この場合、Enum.GetValuesの呼び出しは次のように記述できます。
[Enum].GetValues(GetType(T))
引用返信 編集キー/
■90598 / inTopicNo.3)  Re[2]: EnumからDictionaryを作る拡張メソッド
□投稿者/ 魔界の仮面弁士 (2128回)-(2019/03/23(Sat) 12:25:45)
No90596 (Hongliang さん) に返信
> 拡張メソッドにする意義が分かりません。
> Public Function EnumToDictionary(Of T)() As Dictionary(Of String, T)
> と言う関数をモジュールに定義すれば十分ではないでしょうか。

自分も同意見です。

もしも Module にしたくないのであれば、
  Dim dic = EnumUtil(Of DayOfWeek).ToDictionary()
というような実装にするという手もあります。


' Partial Public NotInheritable Class EnumUtil(Of TEnum As Enum) 'VB 15.8 時点ではまだサポートされていないので
Partial Public NotInheritable Class EnumUtil(Of TEnum As Structure) '値型制約で代用
 Shared Sub New()
  Debug.Assert(GetType(TEnum).IsEnum, "列挙型ではありません。") '制約不足をアサーションで補う
 End Sub
 Public Shared Function ToDictionary() As Dictionary(Of String, TEnum)
  Return [Enum].GetNames(GetType(TEnum)).ToDictionary(
   Function(x) x,
   Function(x) DirectCast([Enum].Parse(GetType(TEnum), x), TEnum))
 End Function
End Class



No90595 (yoshi さん) に返信
> 環境:VB2017、.Net4.72
4.72 ではなく
4.7.2 ですよね。


> Dim dic =[Enum].ToDictionary(GetType(DayOfWeek))

なんだか前提条件がいろいろとおかしいです…。
Shared なメソッドのように振る舞う拡張メソッドは作れませんよ。

上記の ToDictionary は、Enum クラスに対する Shared なメソッドであるかのように書かれていますが、
拡張メソッドは、「インスタンスメソッドのように振る舞う」ためのシンタックスシュガーです。


仮に Shared な拡張メソッド構文が存在していたとしても、
その呼び出しでは型パラメーターが無いので、戻り値の型をコンパイル時に決定できませんよね。
 [Enum].ToDictionary(Of DayOfWeek)( )
あるいは、
 DayOfWeek.ToDictionary( )
あたりであれば決定できますが、いずれにせよ現時点ではありえない構文ですし、
拡張メソッドの出番は無さそうです。



> Enumの名前をキーとするDictionaryを作る拡張メソッドを以下のように作りました。

VB 15.8 時点では (Of TEnum As Enum) はサポートされていませんが、
C# 7.3 であれば、where TEnum : Enum がサポートされていますので、

 // Dictionary<string, DayOfWeek> が返却される
 var result = default(DayOfWeek).ToDictionry();

のように使える拡張メソッドを書くこともできます。

public static Dictionary<string, TEnum> ToDictionry<TEnum>(this TEnum _) where TEnum : Enum
 => Enum.GetNames(typeof(TEnum)).ToDictionary(x => x, x => (TEnum)Enum.Parse(typeof(TEnum), x));
引用返信 編集キー/
■90599 / inTopicNo.4)  Re[3]: EnumからDictionaryを作る拡張メソッド
□投稿者/ yoshi (2回)-(2019/03/23(Sat) 12:53:30)
了解、致しました。大御所のお二方の仰せのように、拡張メソッドではなく、
普通の関数として定義するようにします。

どうもありがとうございました。
解決済み
引用返信 編集キー/
■90600 / inTopicNo.5)  Re[1]: EnumからDictionaryを作る拡張メソッド
□投稿者/ 魔界の仮面弁士 (2129回)-(2019/03/23(Sat) 12:56:14)
追加でもう一点。

No90595 (yoshi さん) に返信
> Return [Enum].GetValues(type).Cast(Of T)().
> ToDictionary(Function(x) x.ToString(), Function(x) x)

GetValues() を基点とするのではなく、
GetNames() から始めた方が良いかもしれません。


たとえば Keys 列挙型の場合、Keys.Return と Keys.Enter のどちらも「13」なので、
値を基点とした場合、Dictionary 化の際にキー重複に陥るかと思います。
引用返信 編集キー/
■90601 / inTopicNo.6)  Re[2]: EnumからDictionaryを作る拡張メソッド
□投稿者/ yoshi (3回)-(2019/03/23(Sat) 13:12:47)
No90600 (魔界の仮面弁士 さん) に返信
> GetValues() を基点とするのではなく、
> GetNames() から始めた方が良いかもしれません。
>
>
> たとえば Keys 列挙型の場合、Keys.Return と Keys.Enter のどちらも「13」なので、
> 値を基点とした場合、Dictionary 化の際にキー重複に陥るかと思います。

列挙型に同じ値を割り当てられるのですね。今まで知りませんでした。
GetNames() から始めるように修正します。
解決済み
引用返信 編集キー/
■90602 / inTopicNo.7)  Re[3]: EnumからDictionaryを作る拡張メソッド
□投稿者/ yoshi (4回)-(2019/03/23(Sat) 13:30:30)
No90601 (yoshi さん) に返信
> 列挙型に同じ値を割り当てられるのですね。今まで知りませんでした。
> GetNames() から始めるように修正します。

後から、検索する方の為に、修正版を置いときます。

Public Function EnumToDictionary(Of T)() As Dictionary(Of String, T)
Return [Enum].GetNames(GetType(T)).
ToDictionary(Function(x) x, Function(x) DirectCast([Enum].Parse(GetType(T), x), T))
End Function
解決済み
引用返信 編集キー/
■90603 / inTopicNo.8)  Re[4]: EnumからDictionaryを作る拡張メソッド
□投稿者/ 魔界の仮面弁士 (2130回)-(2019/03/23(Sat) 15:56:38)
No90602 (yoshi さん) に返信
>> GetNames() から始めるように修正します。
> 後から、検索する方の為に、修正版を置いときます。

この修正版は No90598 と同じ実装ですね。
(型パラメーターの受け取り箇所は異なりますけれども)


> Function(x) DirectCast([Enum].Parse(GetType(T), x), T)

.NET Framework だと、そうするしか無いんですよね。
.NET Core 2.0 以降なら DirectCast せずに T を得られるのですが。


Public Function EnumToDictionary(Of T As Structure)() As Dictionary(Of String, T)
  Return [Enum].GetNames(GetType(T)).ToDictionary(
   Function(x) x,
   Function(x) [Enum].Parse(Of T)(x))
End Function
解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ