읽기 전용 속성에서 사전에 대한 참조를 반환합니다. 소비자가 내 데이터를 변경하지 못하게하려면 어떻게합니까? 이것이 있다면 IList
나는 단순히 그것을 반환 할 수 AsReadOnly
있습니다. 사전으로 할 수있는 일이 있습니까?
Private _mydictionary As Dictionary(Of String, String)
Public ReadOnly Property MyDictionary() As Dictionary(Of String, String)
Get
Return _mydictionary
End Get
End Property
답변
다음은 사전을 감싸는 간단한 구현입니다.
public class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private readonly IDictionary<TKey, TValue> _dictionary;
public ReadOnlyDictionary()
{
_dictionary = new Dictionary<TKey, TValue>();
}
public ReadOnlyDictionary(IDictionary<TKey, TValue> dictionary)
{
_dictionary = dictionary;
}
#region IDictionary<TKey,TValue> Members
void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
{
throw ReadOnlyException();
}
public bool ContainsKey(TKey key)
{
return _dictionary.ContainsKey(key);
}
public ICollection<TKey> Keys
{
get { return _dictionary.Keys; }
}
bool IDictionary<TKey, TValue>.Remove(TKey key)
{
throw ReadOnlyException();
}
public bool TryGetValue(TKey key, out TValue value)
{
return _dictionary.TryGetValue(key, out value);
}
public ICollection<TValue> Values
{
get { return _dictionary.Values; }
}
public TValue this[TKey key]
{
get
{
return _dictionary[key];
}
}
TValue IDictionary<TKey, TValue>.this[TKey key]
{
get
{
return this[key];
}
set
{
throw ReadOnlyException();
}
}
#endregion
#region ICollection<KeyValuePair<TKey,TValue>> Members
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
{
throw ReadOnlyException();
}
void ICollection<KeyValuePair<TKey, TValue>>.Clear()
{
throw ReadOnlyException();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return _dictionary.Contains(item);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
_dictionary.CopyTo(array, arrayIndex);
}
public int Count
{
get { return _dictionary.Count; }
}
public bool IsReadOnly
{
get { return true; }
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
throw ReadOnlyException();
}
#endregion
#region IEnumerable<KeyValuePair<TKey,TValue>> Members
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return _dictionary.GetEnumerator();
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
private static Exception ReadOnlyException()
{
return new NotSupportedException("This dictionary is read-only");
}
}
답변
.NET 4.5
.NET Framework 4.5 BCL에 ReadOnlyDictionary<TKey, TValue>
( source )가 도입되었습니다 .
.NET Framework 4.5 BCL에는 AsReadOnly
사전 용이 포함되어 있지 않으므로 원하는 경우 직접 작성해야합니다. 다음과 같을 것입니다. 단순성은 아마도 .NET 4.5의 우선 순위가 아닌 이유를 강조합니다.
public static ReadOnlyDictionary<TKey, TValue> AsReadOnly<TKey, TValue>(
this IDictionary<TKey, TValue> dictionary)
{
return new ReadOnlyDictionary<TKey, TValue>(dictionary);
}
.NET 4.0 이하
.NET 4.5 이전 Dictionary<TKey, TValue>
에는 ReadOnlyCollection을 감싸는 것처럼 List 를 감싸는 .NET Framework 클래스가 없습니다 . 그러나 하나를 만드는 것은 어렵지 않습니다.
다음은 예 입니다. Google이 ReadOnlyDictionary를 사용하는 경우 많은 다른 것들이 있습니다 .
답변
최근 BUILD 컨퍼런스 에서 .NET 4.5 이후 인터페이스 System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>
가 포함 되었다고 발표 되었습니다. 증명은 여기 (Mono)와 여기 (Microsoft)입니다.)
ReadOnlyDictionary
포함되어 있는지 확실하지 않지만 적어도 인터페이스를 사용하면 공식 .NET 일반 인터페이스를 제공하는 구현을 만드는 것이 어렵지 않아야합니다. 🙂
답변
간단한 래퍼를 사용하십시오. IDictionary를 구현하지 않으므로 런타임에 사전을 변경하는 사전 메서드에 대해 예외를 throw하지 않아도됩니다. 변경 방법은 단순히 존재하지 않습니다. IReadOnlyDictionary라는 자체 인터페이스를 만들었습니다.
public interface IReadOnlyDictionary<TKey, TValue> : IEnumerable
{
bool ContainsKey(TKey key);
ICollection<TKey> Keys { get; }
ICollection<TValue> Values { get; }
int Count { get; }
bool TryGetValue(TKey key, out TValue value);
TValue this[TKey key] { get; }
bool Contains(KeyValuePair<TKey, TValue> item);
void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex);
IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator();
}
public class ReadOnlyDictionary<TKey, TValue> : IReadOnlyDictionary<TKey, TValue>
{
readonly IDictionary<TKey, TValue> _dictionary;
public ReadOnlyDictionary(IDictionary<TKey, TValue> dictionary)
{
_dictionary = dictionary;
}
public bool ContainsKey(TKey key) { return _dictionary.ContainsKey(key); }
public ICollection<TKey> Keys { get { return _dictionary.Keys; } }
public bool TryGetValue(TKey key, out TValue value) { return _dictionary.TryGetValue(key, out value); }
public ICollection<TValue> Values { get { return _dictionary.Values; } }
public TValue this[TKey key] { get { return _dictionary[key]; } }
public bool Contains(KeyValuePair<TKey, TValue> item) { return _dictionary.Contains(item); }
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { _dictionary.CopyTo(array, arrayIndex); }
public int Count { get { return _dictionary.Count; } }
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return _dictionary.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return _dictionary.GetEnumerator(); }
}
답변
isReadOnly의상의 IDictionary<TKey,TValue>
로부터 상속된다 ICollection<T>
( IDictionary<TKey,TValue>
연장 ICollection<T>
같이 ICollection<KeyValuePair<TKey,TValue>>
). 어떤 식 으로든 사용되거나 구현되지 않으며 실제로 연관된 ICollection<T>
멤버 를 명시 적으로 구현하여 “숨겨져”있습니다 .
문제를 해결하기 위해 볼 수있는 방법은 적어도 3 가지가 있습니다.
IDictionary<TKey, TValue>
제안 된대로 사용자 정의 읽기 전용을 구현하고 내부 사전에 랩 / 위임ICollection<KeyValuePair<TKey,
세트를 읽기 전용으로 또는
TValue>>
IEnumerable<KeyValuePair<TKey,
값 사용에 따라 반환
TValue>>- 복사 생성자를 사용하여 사전을 복제하고 사본
.ctor(IDictionary<TKey,
을 리턴하십시오. 사용자가 원하는대로 자유롭게 사용할 수 있으며 소스 사전을 호스트하는 오브젝트의 상태에 영향을 미치지 않습니다. 복제중인 사전에 참조 유형 (예제에 표시된 문자열이 아님)이 포함 된 경우 “수동으로”복사를 수행하고 참조 유형도 복제해야합니다.
TValue>)
여담으로; 컬렉션을 노출 할 때 가능한 가장 작은 인터페이스를 노출하는 것을 목표로합니다. 예제의 경우 유형이 노출하는 공개 계약을 위반하지 않고 기본 구현을 변경할 수 있으므로 IDictionary 여야합니다.
답변
읽기 전용 사전은 어느 정도 대체 될 수 있습니다 Func<TKey, TValue>
.-검색을 수행하는 사람들 만 원할 경우 일반적으로 API에서이를 사용합니다. 간단하고, 특히 원하는 경우 백엔드를 교체하는 것이 간단합니다. 그러나 키 목록은 제공하지 않습니다. 중요한 것은 당신이하는 일에 달려 있습니다.
답변
아니요,하지만 쉽게 롤업 할 수 있습니다. IDictionary는 IsReadOnly 속성을 정의합니다. 사전을 포장하고 적절한 메소드에서 NotSupportedException을 던지기 만하면됩니다.