我有一本字典如下:
public enum Role { Role1, Role2, Role3, }
public enum Action { Action1, Action2, Action3, }
var dictionary = new Dictionary<Role, List<Action>>();
dictionary.Add(RoleType.Role1, new Action [] { Action.Action1, Action.Action2 }.ToList());
现在我希望能够构建一个只读字典,其值类型也是只读的,如下所示:
var readOnlyDictionary = new ReadOnlyDictionary<Role, ReadOnlyCollection<Action>>(dictionary);
由于TValue
类型的差异,最后一行显然会导致编译时错误。
使用List<TValue>
也是必要的,因为原始字典是以编程方式从外部源填充的。
有没有简单的方法来执行此转换?
答案 0 :(得分:8)
一种可能性(对于大型集合可能不是最理想的)是构造所需类型的新Dictionary
对象(使用Enumerable.ToDictionary overload)并使用List.AsReadOnly() extension这样:
var readOnlyDictionary =
new ReadOnlyDictionary<Role, ReadOnlyCollection<Action>>
(dictionary.ToDictionary(k => k.Key, v => v.Value.AsReadOnly()));
答案 1 :(得分:1)
将近 5 年之后,这里有一个简单的解决方案,它可以适应字典,正确处理值类型的协方差。
Option Explicit
Sub lookupClientEmails()
' Source
Const sName As String = "Orders"
Const sFirstRow As Long = 2
Const sLookup As String = "C" ' 3
Const sResultOffset As Long = 1 ' referring to column 'D'
' Destination
Const dName As String = "Clients"
Const dFirstRow As Long = 2
Const dLookup As String = "M" ' 13
Const dResult As String = "V" ' 22
' Workbook
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' Source
Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
Dim sLastRow As Long
sLastRow = sws.Cells(sws.Rows.Count, sLookup).End(xlUp).Row
Dim srg As Range
Set srg = sws.Cells(sFirstRow, sLookup).Resize(sLastRow - sFirstRow + 1)
' Destination
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
Dim dLastRow As Long
dLastRow = dws.Cells(dws.Rows.Count, dLookup).End(xlUp).Row
' Variables
Dim sCell As Range
Dim i As Long
Dim FirstAddress As String
' Loop
For i = dFirstRow To dLastRow
Set sCell = srg.Find(dws.Cells(i, dLookup).Value, _
srg.Cells(srg.Rows.Count), xlFormulas, xlWhole)
If Not sCell Is Nothing Then
FirstAddress = sCell.Address
Do
If sCell.Offset(, sResultOffset).Value <> "" Then
dws.Cells(i, dResult).Value _
= sCell.Offset(, sResultOffset).Value
Exit Do
End If
Set sCell = srg.FindNext(sCell)
Loop While sCell.Address <> FirstAddress
End If
Next i
End Sub