I have a class in C# that contains a Dictionary, which I want to create and ensure nothing as added, edited or removed from this dictionary as long as the class which contains it exists.
readonly doesn't really help, once I tested and saw that I can add items after. Just for instance, I created an example:
public class DictContainer
{
private readonly Dictionary<int, int> myDictionary;
public DictContainer()
{
myDictionary = GetDictionary();
}
private Dictionary<int, int> GetDictionary()
{
Dictionary<int, int> myDictionary = new Dictionary<int, int>();
myDictionary.Add(1, 2);
myDictionary.Add(2, 4);
myDictionary.Add(3, 6);
return myDictionary;
}
public void Add(int key, int value)
{
myDictionary.Add(key, value);
}
}
I want the Add method not to work. If possible, I want it not to even compile. Any suggestions?
Actually, I'm worried for it is code that will be open for a lot of people to change. So, even if I hide the Add method, it will be possible for someone to "innocently" create a method which add a key, or remove another. I want people to look and know they shouldn't change the dictionary in any ways. Just like I have with a const variable.
Hide the Dictionary totally. Just provide a get method on the DictContainer class that retrieves items from the dictionary.
public class DictContainer
{
private readonly Dictionary<int, int> myDictionary;
public DictContainer()
{
myDictionary = GetDictionary();
}
private Dictionary<int, int> GetDictionary()
{
Dictionary<int, int> myDictionary = new Dictionary<int, int>();
myDictionary.Add(1, 2);
myDictionary.Add(2, 4);
myDictionary.Add(3, 6);
return myDictionary;
}
public this[int key]
{
return myDictionary[key];
}
}
Don't define the Add Method.
Keep the myDictionary variable private and expose a Getter/Indexer so that it can only be read from outside that class..
There's no built-in way to do that, consider using a wrapper class.
interface IReadOnlyDic<Key, Value>
{
void Add(Key key, Value value);
}
class ReadOnlyDic<Key, Value> : Dictionary<Key, Value>, IReadOnlyDic<Key, Value>
{
public new void Add(Key key, Value value)
{
//throw an exception or do nothing
}
#region IReadOnlyDic<Key,Value> Members
void IReadOnlyDic<Key, Value>.Add(Key key, Value value)
{
base.Add(key, value);
}
#endregion
}
to add custom items;
IReadOnlyDic<int, int> dict = myDictInstance as IReadOnlyDic<int, int>;
if (dict != null)
dict.Add(1, 155);
and this is another way
class ReadOnlyDic<Key, Value> : Dictionary<Key, Value>
{
private bool _locked = false;
public new void Add(Key key, Value value)
{
if (!_locked)
{
base.Add(key, value);
}
else
{
throw new ReadOnlyException();
}
}
public void Lock()
{
_locked = true;
}
}
FYI, now it is built-in to .net 4.5.
http://msdn.microsoft.com/en-us/library/gg712875(v=vs.110).aspx
Similar to Neil's answer:
Hide the Dictionary totally. Just provide a get method on the DictContainer class that retrieves items from the dictionary. If you want to use [] override you need getter settter method (atleast any one get/set)
public class DictContainer
{
private readonly Dictionary<int, int> myDictionary;
public DictContainer()
{
myDictionary = GetDictionary();
}
private Dictionary<int, int> GetDictionary()
{
Dictionary<int, int> myDictionary = new Dictionary<int, int>();
myDictionary.Add(1, 2);
myDictionary.Add(2, 4);
myDictionary.Add(3, 6);
return myDictionary;
}
public this[int key]
{
get => myDictionary[key];
}
}
Related
I have a class, with some global and constant dictionaries. Like:
public static class Constants
{
public static Dictionary<string, MyObject> MyDictionary= new Dictionary<string, MyObject>()
{
{"first", new MyObject()},
{"second", new MyObject()},
};
}
Lets say I would like another dictionary, to be like that only with some added and removed elements. Is there a way to achieve that, within the static class? I imagine something like:
public static Dictionary<string, MyObject> MyOtherDictionary = MyDictionary.Remove("second").Add("Third", new MyObject())
But I know that does not work, so is there any way I can achieve this?
No, that doesnt work in this way for two reasons:
Remove returns a bool, you can't use Add on a bool
even if you make it compile, you don't want to modify the other dictionary but you want to create a new dictionary which contains similar items, you can use the constructor:
public static Dictionary<string, MyObject> MyOtherDictionary;
// ...
static Constants
{
MyOtherDictionary = new Dictionary<string, MyObject>(MyDictionary);
MyOtherDictionary.Remove("second");
MyOtherDictionary.Add("Third", new MyObject());
}
You could do it using properties instead
public static class Constants
{
public static Dictionary<string, MyObject> myDictionary
{
get
{
return new Dictionary<string, MyObject>()
{
{ "first", new MyObject()},
{ "second", new MyObject()},
};
}
}
static Dictionary<string, MyObject> _myOtherDictionary;
public static Dictionary<string, MyObject> myOtherDictionary
{
get
{
_myOtherDictionary = myDictionary;
_myOtherDictionary.Remove("first");
_myOtherDictionary.Add("third", new MyObject());
return _myOtherDictionary;
}
}
}
I have an ASP.NET MVC app. I need a Dictionary<string, string> that is available throughout the entire app at runtime. My question is, where is the best place/way to define this Dictionary? I assume I need to do it in the Global.asax file. Yet, I'm not sure.
Create a utility class and use Lazy to pospone intialization until the first hit:
public static class InfoHelper
{
private static Lazy<ConcurrentDictionary<string, string>> infoBuilder
= new Lazy<ConcurrentDictionary<string, string>>( () => SomeCreationMethod() );
public static ConcurrentDictionary<string, string> Info
{
get
{
return infoBuilder.Value;
}
}
Or, using HttpContext.Cache:
public static class InfoHelper
{
public static ConcurrentDictionary<string, string> Info
{
get
{
ConcurrentDictionary<string, string> d
= HttpContext.Current.Cache["someId"] as ConcurrentDictionary<string, string>;
if (d == null)
{
d = HttpContext.Current.Cache["someId"] = SomeCreationMethod();
}
return d;
}
}
Or, when setting this from an external class:
public static class InfoHelper
{
public static ConcurrentDictionary<string, string> Info
{
get
{
return HttpContext.Current.Cache["someId"] as ConcurrentDictionary<string, string>;
}
set
{
HttpContext.Current.Cache["someId"] = value;
}
}
Then set it from another class:
InfoHelper.Info = ...;
I have a class like:
public class Something
{
private Dictionary<int,int> dic;
public Something()
{
dic = new Dictionary<int,int>();
}
public Something(Dictionary<int,int> a)
{
dic = new Dictionary<int,int>();
}
}
How can I avoid initializing the collection twice?
I guess you are looking for chaining constructor:
public class Something
{
private Dictionary<int, int> dic;
public Something()
: this(new Dictionary<int, int>())
{
}
public Something(Dictionary<int, int> a)
{
dic = a;
}
}
Call this():
public Something()
{
dic = new Dictionary<int,int>();
}
public Something(Dictionary<int,int> a) : this()
{
// do something with a??
}
note that the "default" constructor is NOT called by default form other constructors, so you're not really initializing the dictionary twice.
There is another alternative:
public class Something
{
private Dictionary<int, int> dic;
private void Initialize()
{
dic = new Dictionary<int, int>();
}
public Something()
{
Initialize();
}
public Something(Dictionary<int, int> a)
{
Initialize();
// do something with a??
// Yes, you are not using the parameter "a".
// I don't know if this is intentional.
}
}
Note: this wont work for readonly fields.
By the way, as I mentioned you can chain the constructors. The compiler can optimize it.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have a working example of a Dictionary<string, int>. I have a requirement to set the Dictionary to a private Dictionary and check the value.
Currently I have:
protected void btnSubmit_Click(object sender, EventArgs e)
{
Dictionary<string, int> docTypeValue = new Dictionary<string, int>();
docTypeValue.Add("OSD", 1);
docTypeValue.Add("POD", 2);
docTypeValue.Add("REC", 3);
docTypeValue.Add("CLAINF", 4);
docTypeValue.Add("RATE", 5);
docTypeValue.Add("OTHER", 6);
docTypeValue.Add("CARINV", 7);
docTypeValue.Add("PODDET", 8);
docTypeValue.Add("BOLPO", 9);
litText.Text = docTypeValue[txtDocType.Text].ToString();
}
This works as expected. Would I need to make use of a property? ie below
private Dictionary<string, int> DocTypeValue
{
get;
set;
}
How can I refactor what I have above to create the suggested private Dictionary?
You're looking for something like this. Make use of the Collection Initializer feature.
private Dictionary<string, int> docTypeValue = new Dictionary<string, int>
{
{ "OSD", 1 },
{"POD", 2},
{"REC", 3},
{"CLAINF", 4},
//...
};
If you don't want non-members to be able to modify the contents of the dictionary, but want to make it available it is possible to do something like this:
private Dictionary<String, Int32> dictionary = ...
public IEnumerable<Int32> Dictionary { get{ return dictionary.Values; } }
// Other methods in the class can still access the 'dictionary' (lowercase).
// But external users can only see 'Dictionary' (uppercase).
void AddItemToDictoinary(String key, Int32 value) {
dictionary.Add(key, value); // dictionary is accessible within the class.
}
or using an indexer like this:
private Dictionary<String, Int32> dictionary = ...
public Int32 this[String key] { get { return dictionary[key]; } }
// Same as above - within the class you can still add items to the dictionary.
void AddItemToDictoinary(String key, Int32 value) {
dictionary.Add(key, value);
}
using the indexer takes advantage of the BST behind Dictionary<T, U> (rather than using sequential search). So if you're dictionary is defined like so:
class SneakyDictionary {
private Dictionary<String, Int32> dictionary = ...
public Int32 this[String key] { get { return dictionary[key]; } }
// Same as above - within the class you can still add items to the dictionary.
void AddItemToDictoinary(String key, Int32 value) {
dictionary.Add(key, value);
}
}
You would use it like this:
public static void Main() {
SneakyDictionary dictionary = ...
dictionary.AddItemToDictionary("one", 1);
dictionary.AddItemToDictionary("two", 2);
dictionary.AddItemToDictionary("three", 3);
// Access items in dictionary using indexer:
Console.WriteLine(dictionary["one"]);
}
It's a matter of range. If your dictionary is useful for the whole class you could instantiate it a as private static (or not) readonly field with initializer :
private static readonly Dictionary<string, int> docTypeValue = new Dictionary<string, int>
{
{ "OSD", 1 },
{"POD", 2},
{"REC", 3},
{"CLAINF", 4},
// and so on
};
But you could also rely on a .Net feature which is called static constructor :
private static Dictionary<string, int> docTypeValue;
static YOURCLASSNAME()
{
docTypeValue = new Dictionary<string, int>();
docTypeValue.Add("OSD", 1);
// and so on
}
Or a combination of these.
In both cases your dictionary will be initialized once, against your current approach.
If it's a private member you don't need a property, just use -
private Dictionary<string, int> _docTypeValue;
As per my understanding about your requirement " I have a requirement to set the Dictionary to a private Dictionary and check the value." you need to have this dictionary on the class level you do not need to create property for the dictionary just create it as a private dictionary.
similar as in the above answer.
I need to create a dictionary that has 2 values per key, and it must return one of the 2 values with the same probability.
Example:
myDicry
{
key = "A", value1=15, value2=56;
}
int firstCall = myDicry["A"]; // = 15
int secondCall = myDicry["A"]; // = 56
It would be possible to write an IDictionary<TKey, TValue> implementation that behaved in this manner, but that would not be a good idea: most people would find a non-deterministic indexer for a collection-class very unintuitive.
Instead, I suggest you make this the responsibility of the value for a key, rather than the Dictionary itself. One option would be to write a custom-type that is capable of picking from a set of possibilities with equal probability. For example:
public class UnbiasedRandomPicker<T>
{
private readonly Random _rand = new Random();
private readonly T[] _possibilities;
public UnbiasedRandomPicker(params T[] possibilities)
{
// argument validation omitted
_possibilities = possibilities;
}
public T GetRandomValue()
{
return _possibilities[_rand.Next(_possibilities.Length)];
}
}
You could then use the dictionary like this:
var dict = new Dictionary<string, UnbiasedRandomPicker<int>>
{
{"A", new UnbiasedRandomPicker<int>(15, 56)},
{"B", new UnbiasedRandomPicker<int>(25, 13)}
};
int randomValueFromA = dict["A"].GetRandomValue();
There's nothing built into the framework to do this, but you'd probably want to implement it by creating a "wrapper" type which had a Dictionary<TKey, Tuple<TValue, TValue>>. You'd then write an indexer to choose appropriately between the two values.
I would actually just implement this in a class that uses a Dictionary<TKey, TValue[]> internally. That way you could even implement the type to have a variable number of values per key.
Like:
class RandomDictionary<TKey, TValue>
{
Dictionary<TKey, TValue[]> m_dict;
Random m_random;
public RandomDictionary()
{
m_dict = new Dictionary<TKey, TValue[]>();
m_random = new Random();
}
public TValue this[TKey key]
{
get
{
TValue[] values = m_dict[key];
return values[m_random.Next(0, values.Length)];
}
}
public void Define(TKey key, params TValue[] values)
{
m_dict[key] = new TValue[values.Length];
Array.Copy(values, m_dict[key], values.Length);
}
public bool TryGetValue(TKey key, out TValue value)
{
TValue[] values;
if (!m_dict.TryGetValue(key, out values))
{
value = default(TValue);
return false;
}
value = values[m_random.Next(0, values.Length)];
return true;
}
}
Use Tuple as dictionary value type.
IDictionary<string, Tuple<int, int>> doubleDictionary = new Dictionary<string, Tuple<int, int>>();
// ...
int secondValue = doubleDictionary["A"].Item2;
You could also write an extension method for the dictionary, so you could create something like this:
IDictionary<string, Tuple<int, int>> doubleDictionary = new Dictionary<string, Tuple<int, int>>();
doubleDictionary.GetRandomValueForKey("A");
Then you can use this with any dictionary.
public static void GetRandomValueForKey(this Dictionary<string, Tuple<int, int>> dict,
string key)
{
... Code to return the value
}
^^ that was written off the top of my head, so please excuse me if this is slightly wrong.
This below code will solve the dictionary part of the problem and make the randomization customizable so that you can apply a level so pseudo-randomness that suits your needs. (or simply hard code it instead of the use of a functor)
public class DoubleDictionary<K, T> : IEnumerable<KeyValuePair<K, T>>
{
private readonly Dictionary<K, Tuple<T, T>> _dictionary = new Dictionary<K, Tuple<T, T>>();
private readonly Func<bool> _getFirst;
public DoubleDictionary(Func<bool> GetFirst) {
_getFirst = GetFirst;
}
public void Add(K Key, Tuple<T, T> Value) {
_dictionary.Add(Key, Value);
}
public T this[K index] {
get {
Tuple<T, T> pair = _dictionary[index];
return GetValue(pair);
}
}
private T GetValue(Tuple<T, T> Pair) {
return _getFirst() ? Pair.Item1 : Pair.Item2;
}
public IEnumerable<K> Keys {
get {
return _dictionary.Keys;
}
}
public IEnumerable<T> Values {
get {
foreach (var pair in _dictionary.Values) {
yield return GetValue(pair);
}
}
}
IEnumerator<KeyValuePair<K, T>> IEnumerable<KeyValuePair<K, T>>.GetEnumerator() {
foreach (var pair in _dictionary) {
yield return new KeyValuePair<K, T>(pair.Key, GetValue(pair.Value));
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return ((IEnumerable<KeyValuePair<K, T>>)this).GetEnumerator();
}
}