I guess I've seen it somewhere before, but now I can't remember nor find it. Is there a way to make a getter property with arguments?
I mean, as I can convert "float getSize();" to "float Size":
float getSize() {
return this.size;
}
float Size {
get { return this.size; }
}
Then, could I convert, for example, "float getSize(String unit);" to "float Size(String unit)" or something like that?
float getSize(String unit) {
return this.size;
}
float Size(String unit) {
get {
if (unit == Unit.Meters)
return this.size/100;
else
return this.size;
}
}
I think there's no really problem of using function at all, but may look better this way :P
To answer the question: No, it is not possible, and as already pointed out, a getter with a parameter would look just like a method.
The thing you are thinking about might be an indexed default property, which looks like this:
class Test
{
public string this[int index]
{
get { return index.ToString(); }
}
}
This allows you to index into an instance of Test, like this:
Test t = new Test();
string value = t[1];
Interestingly, having a property with parameter is possible in VB.NET, like this:
Public ReadOnly Property oPair(param As String) As Result
Get
'some code depends on param
End Get
End Property
It's not superior to a regular function, but sometimes it is nice to have such a possibility.
I know this is an old post, but I ran into wanting to do this today in C#. Whether that's a good thing or not is probably falling on the 'not' side. However, I ran across an interesting idea posted by Mark Jones at (https://social.msdn.microsoft.com/forums/en-US/5a25bc83-990e-4657-aa9c-69bca5158d48/overloaded-c-properties-with-arguments?prof=required), but I didn't quite like the feel of it.
So I wrote my own based on his (mine is in .Net 5.0 with Nullable = enable):
class ParameterizedProperty<T>
{
private readonly Func<int, T> getter;
private readonly Action<int, T> setter;
public T this[int index]
{
get => this.getter(index);
set => this.setter(index, value);
}
public ParameterizedProperty(Func<int, T> getter, Action<int, T> setter)
{
this.getter = getter;
this.setter = setter;
}
}
class NamedParameterizedProperty<T>
{
private readonly Func<int, T> indexedGetter;
private readonly Action<int, T> indexedSetter;
private readonly Func<string, T> namedGetter;
private readonly Action<string, T> namedSetter;
public T this[int index]
{
get => this.indexedGetter(index);
set => this.indexedSetter(index, value);
}
public T this[string name]
{
get => this.namedGetter(name);
set => this.namedSetter(name, value);
}
public NamedParameterizedProperty(Func<int, T> indexedGetter, Action<int, T> indexedSetter, Func<string, T> namedGetter, Action<string, T> namedSetter)
{
this.indexedGetter = indexedGetter;
this.indexedSetter = indexedSetter;
this.namedGetter = namedGetter;
this.namedSetter = namedSetter;
}
}
class ReadOnlyParameterizedProperty<T>
{
private readonly Func<int, T> getter;
public T this[int index] => this.getter(index);
public ReadOnlyParameterizedProperty(Func<int, T> getter)
{
this.getter = getter;
}
}
class ReadOnlyNamedParameterizedProperty<T>
{
private readonly Func<int, T> indexedGetter;
private readonly Func<string, T> namedGetter;
public T this[int index] => this.indexedGetter(index);
public T this[string name] => this.namedGetter(name);
public ReadOnlyNamedParameterizedProperty(Func<int, T> indexedGetter, Func<string, T> namedGetter)
{
this.indexedGetter = indexedGetter;
this.namedGetter = namedGetter;
}
}
So a little about my solution: I opted for Func<> & Action<> for the getters/setters because I didn't want this helper class to have to need any knowledge of underlying property it would be supporting. Instead, the class that owns the property would have public (or private) methods for get_X / set_X (or whatever naming convention you wish to use) that would handle everything - such as validation.
Now as to my use case for this: I had a class that has an internal array of a specific type. I have a default indexer property public primaryType this[int index], but it has a couple of other types that it understands and can convert to / from for primaryType. However, I can't do public otherType this[int index], and I didn't really want to do public methods called something like 'get_OtherType` & 'set_OtherType'.
These helper classes let me do something like:
public ParameterizedProperty<OtherType> OtherType { get; }
public MyClass()
{
this.OtherType = new(get_OtherType, set_OtherType);
}
private OtherType get_OtherType(int index)
{
/* validate index, convert PrimaryType at index to OtherType and return. */
}
private void set_OtherType(int index, OtherType value)
{
/* validate index, validate value, convert to PrimaryType and set to internal array. */
}
Then in other classes / UIs that use this class, where 'OtherType' is more convenient for them to work with then 'PrimaryType', I can have them doing things like myClass1.OtherType[0] = otherType;, but if they work with the primary type, then they can do myClass1[0] = primaryType - or if I just want to be consistent / explicit, I don't have a default indexer property, and I use a ParameterizedProperty for the primary type as well, IE: myClass1.PrimaryType[0] = primaryType;
Again, whether this is a good idea to go this route or not, I'm unsure.
It is possible for a class object to reasonably-efficiently have something that behaves as a named indexed property getter by having a property return a struct which simply holds a private reference to the class object and includes an indexed property getter which chains to a method in the class. Such a single-item structure can be generated at basically no cost (it can likely fit in a register, and will be loaded with a value that's in another register; the JIT may even be able to recognize that the same register can be used for both purposes), so if using such a getter makes code more readable that's a substantial argument in favor.
Unfortunately, the inability of struct members to indicate whether or not they modify the underlying structure makes it impossible to use the same approach for an indexed property setter. Even though it would be helpful it one could have have an OrderedCollection<T> with something like:
struct ByIndexAccessor {
OrderedCollection<T> owner;
ByIndexAccessor(OrderedCollection<T> o) { owner = o; }
T this[int index] {
get { return owner.handleGet(index); }
set { owner.handleSet(index, value); }
}
}
ByIndexAccessor ByIndex {
get {return new ByIndexAccessor(this); }
}
and say myCollection.ByIndex[3] = newThing;, C# would reject such code because it has no way of knowing that this particular indexed set implementation can safely be used on a read-only structure.
Related
I need to make a class that wraps two dictionaries together, so that their values can be retrieved by a key of either an int or a string.
Properties seem to be the best approach here, but is there a difference between these two implementations?
public class Atlas<TValue>
{
private Dictionary<int, TValue> _byIndex;
private Dictionary<string, TValue> _byName;
public Dictionary<int, TValue> ByIndex
{
get { return _byIndex; }
}
public Dictionary<string, TValue> ByName
{
get { return _byName; }
}
}
And
public class Atlas<TValue>
{
public Dictionary<int, TValue> ByIndex { get; private set; }
public Dictionary<string, TValue> ByName { get; private set; }
}
In either case, the dictionary object is immutable and the elements can freely be changed, which is what I want. However, trying to change the dictionary object will result in either a ~ cannot be assigned to -- it is read only or a ~ cannot be used in this context because the set accessor is inaccessible. I realize the compiler will fluff out my auto properties into something similar to the top block of code anyways...
Does it actually matter which compiler error is raised?
The only difference is that in the second case the setter is inaccessible, but it is there, while in the firs case there is no accessor at all. This means that a program that uses reflection could potentially access the properties of the second example, while in case of the first example you would need to access fields instead.
As far as non-reflective use is concerned, there is no difference between the two code snippets: outside classes will not be able to set the dictionaries.
You may want to go further and hide the presence of the dictionaries from the users of your classes. Rather than providing two properties of Dictionary type, you may want to hide this detail of implementation from the users of your class by hiding it behind a pair of method:
public class Atlas<TValue> {
public bool TryGetByIndex(int index, out TValue val);
public void Add(int index, TValue val);
public bool TryGetByName(string name, out TValue val);
public void Add(string name, TValue val);
public TValue this[string name] { get ... set ...}
public TValue this[int index] { get ... set ...}
// You may want to add more methods or properties here, for example to iterate atlas elements
}
in java I could easily describe an enum with aditional data.
I could describe it something like this
public enum OperatorType
{
GreaterOrEqual (">=", "GreaterOrEqual"),
Greater (">" ,"Greater"),
Less ("<", "Less"),
LessOrEqual ("<=", "LessOrEqual"),
Equal ("==", "Equal"),
Between ("Between", "Between"),
Around ("Around","Around");
private final String symbol;
private final String name;
private OperatorType(final String symbol, final String name) {
this.symbol = symbol;
this.name = name;
}
}
And then add a static method that iterates over values(), adds all data to a hashmap and allow to retrieve from the map full enum data by one of its attriburtes as a key.
In brief, enum is a very developed type in java.
Now,
moving to c#, what are my options?
I want to hold an enum with its attributes, load it to a map, and retreive by key when I need. Do I have anything to assist (like, a singletone for each enum - which is not a good idea).
Thanks.
I would just create a class with public static readonly instances of each type and ditch enums altogether. You can use them as dictionary keys or do whatever you like. If you still intend to map them to an underlying data type (int) then you can create implicit operators for that too.
public class OperatorType
{
private static readonly Dictionary<int, OperatorType> OperatorMapping = new Dictionary<int, OperatorType>();
public static readonly OperatorType GreaterOrEqual = new OperatorType(0, ">=", "GreaterOrEqual");
public static readonly OperatorType Greater = new OperatorType(1, ">", "Greater");
public readonly String symbol;
public readonly String name;
private readonly int underlyingValue;
private OperatorType(int underlyingValue, string symbol, string name) {
this.underlyingValue = underlyingValue;
OperatorMapping[underlyingValue] = this;
this.symbol = symbol;
this.name = name;
}
public static implicit operator int(OperatorType operatorType)
{
return operatorType.underlyingValue;
}
public static implicit operator OperatorType(int value)
{
return OperatorMapping[value];
}
}
Sample usage:
Dictionary<OperatorType, string> operators = new Dictionary<OperatorType, string>();
operators.Add(OperatorType.GreaterOrEqual, "Greater or equal");
Console.WriteLine(operators[OperatorType.GreaterOrEqual]); //"Greater or equal"
OperatorType operatorType = 1;
Console.WriteLine(operatorType.name); //"Greater"
If you don't care about an underlying value, don't include it. Also consider whether or not the Dictionary mapping should be threadsafe for your usage. You can also expose a static IEnumerable<OperatorType> (or other collection) to get all operators defined if you want.
EDIT: On second thought, explicit operators are possibly preferable instead of implicit, both to conform with typical .NET best practices and to better match typical enum conversions.
The most convinient workaround might be to create an extension method to your enum type, and return the associated symbols.
Something like this:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
tester t = tester.x;
t.testenums();
Console.ReadKey();
}
}
public static class ext
{
public static void testenums(this tester x)
{
Console.WriteLine(x.ToString());
}
}
public enum tester
{
x,
y
}
}
Of course you can write a more complex extension method, with return value, etc, this is just an example how to do it.
You can create an attribute:
public class EnumKeyAttribute : Attribute
{
public string Key { get; set; }
public string Description { get; set; }
public EnumKeyAttribute(string key, string description)
{
this.Key = key;
this.Description = description;
}
}
Then apply it to your enum
public enum OperatorType
{
[EnumKey(">=", "GreaterOrEqual")]
GreaterOrEqual,
[EnumKey(">", "Greater")]
Greater,
[EnumKey("<", "Less")]
Less,
[EnumKey("<=", "LessOrEqual")]
LessOrEqual,
[EnumKey("==", "Equal")]
Equal,
[EnumKey("Between", "Between")]
Between,
[EnumKey("Around", "Around")]
Around
}
To get the attribute data you can use reflection. Below is an example of getting the attribute for "Less"
MemberInfo memberInfo = typeof(OperatorType).GetMember(OperatorType.Less.ToString()).FirstOrDefault();
if(memberInfo != null)
{
EnumKeyAttribute attribute = (EnumKeyAttribute)memberInfo.GetCustomAttributes(typeof(EnumKeyAttribute), false).FirstOrDefault();
Console.WriteLine(attribute.Key);
Console.WriteLine(attribute.Description);
}
But because these enums are not created at runtime you can increase your efficiency by creating a static method that looks up the value in a dictionary. Do this as an extension method for ease of use
public static class KeyFinder
{
private static Dictionary<OperatorType, EnumKeyAttribute> lookupTable =
new Dictionary<OperatorType, EnumKeyAttribute>();
public static EnumKeyAttribute GetKey(this OperatorType type)
{
if (lookupTable.ContainsKey(type))
{
return lookupTable[type];
}
MemberInfo memberInfo = typeof(OperatorType).GetMember(type.ToString()).FirstOrDefault();
if (memberInfo != null)
{
EnumKeyAttribute attribute = (EnumKeyAttribute)memberInfo.GetCustomAttributes(typeof(EnumKeyAttribute), false).FirstOrDefault();
if (attribute != null)
{
lookupTable.Add(type, attribute);
return attribute;
}
}
// add a null value so next time it doesn't use reflection only to find nothing
lookupTable.Add(type, null);
return null;
}
}
So now to get the values you simply do the following:
OperatorType.Less.GetKey().Key
OperatorType.Less.GetKey().Description
Just be careful of null reference exceptions (since it will return null if it can't find an attribute). If you want to find by key you can simply create other extension methods that use the string value as the key.
C# doesn't really have the same feature. However there are several possibilities to get really close (and potentially more flexible as well).
Sticking to regular enums, you could use attributes to enrich with extra information. Of course, this requires reflection to work with that
public enum OperatorType
{
[DisplayName(">=")]
GreaterOrEqual,
// ...
}
There are several patterns to work with this, e.g. http://www.codeproject.com/Articles/28087/DisplayNameAttribute-for-Enumerations, google for more.
Another approach can be to enhance your enumeration types using regular classes:
public class OperatorType
{
public static OperatorType GreaterOrEqual = new OperatorType(">=", "GreaterOrEqual");
// ...
string symbol;
string name;
private OperatorType(string symbol, string name)
{
this.symbol = symbol;
this.name = name;
}
}
This article describes some other ways to work with enum-like types in C#
If you really need the functionality of Java-style enums in C#, I see three reasonable ways to implement it:
Use a C# enum and a static class of helper methods. You lose type safety, but this is an otherwise very workable solution.
Use a C# enum and a set of extension methods. Probably the most idiomatic C# solution, but you still have to deal with the loss of type safety (your extension methods should be able to cope with out-of-range values, even if only by throwing an exception).
Use the type-safe enum pattern that was common in Java before the language gained the enum keyword in Java 5. If you have non-trivial logic for each enum value, this would be my preference.
I have class called GroupItem, i can store any type here say int, string, decimal, datetime etc.., Then, i have GroupItems which will store any groupItem. I'm using an arraylist to store all the groupItem.
public class GroupItem<T>
{
private string heading;
private List<T> items = new List<T>();
public GroupItem() { }
public string Heading
{
get { return heading; }
set { heading = value; }
}
public List<T> Items
{
get { return items; }
set { items = value; }
}
public void Add(T value)
{
this.items.Add(value);
}
public T this[int index]
{
get
{
return this.items[index];
}
}
}
public class GroupItems
{
private string groupName;
private List<object> items = new List<object>();
public string GroupName
{
get { return groupName; }
set { groupName = value; }
}
public GroupItems() { }
public void Add(object value)
{
this.items.Add(value);
}
public object this[int index]
{
get
{
return this.items[index];
}
}
}
I want to retrieve from GroupItems. How i can get generic item's values in groupItems?
I'm now inserting two items, datetime and int to groupitems. Now i want to retrieve groupitems[2] value but how i can convert this to groupItem without knowing what it is. Even we may get its genericarguments by getType().getGenericarguments()[0]. But how i can create an instance based upon that.
If the list is storing heterogeneous items, then I would suggest you need a common non-generic interface or base-class. So, say we have
interface IGroupItem {
// the non-generic members, and maybe
// "object Value {get;}" etc, and maybe
// "Type ItemTypr {get;}"
}
You would then have:
class GroupItem<T> : IGroupItem {...}
an you would then use
List<IGroupItem> ...
instead of ArrayList, or, franky, in place of GroupItems {...}
What I'd do is create a generic collection such as:
public class GroupItems<T> : List<GroupItem<T>>
{
}
If you need to extend the basic functionality of a list, you could also extend Collection<T> and override the methods you need:
public class GroupItems<T> : Collection<GroupItem<T>>
{
protected override void InsertItem(int index, T item)
{
// your custom code here
// ...
// and the actual insertion
base.InsertItem(index, item);
}
}
How about just replacing your GroupItems class with List<GroupItem<T>> ?
Depending on what you do with GroupItem you should either inherit from List/Collection as was offered by other or use a generic collection inside your class
e.g.
class GroupItem<T>
{
private List<T> items = new List<T>();
public void Add(T value)
{
items.Add(value);
}
public T Get()
{
//replace with some logic to detemine what to get
return items.First();
}
}
There are two situations that could be covered by your question:
You want to simply store a collection of GroupItem's of type T in the class GroupItems.
You want to store a collection of generic GroupItem's of any type in the class GroupItems. To better clarify, I mean that you could store GroupItem<DateTime> or GroupItem<int> in the same GroupItems class.
Here are some ways of going about storing and retrieving for both scenarios:
Same Type
public class GroupItem<T>
{
// ... Code for GroupItem<T>
}
public class GroupItems<T>
{
private List<GroupItem<T>> mItems = new List<GroupItem<T>>();
public void Add(T item)
{
mItems.Add(item);
}
public T GetItem(int index)
{
return mItems[index];
}
}
Here you will build a collections that contain GroupItem's of the same time, so a collection of GroupItem<DateTime> for example. All the items will be of the same type.
Generic Type
public interface IGroupItem
{
// ... Common GroupItem properties and methods
}
public class GroupItem<T>
{
// ... Code for GroupItem<T>
}
public class GroupItems
{
private List<IGroupItem> mItems = new List<IGroupItem>();
public void Add(IGroupItem item)
{
mItems.Add(item);
}
// This is a generic method to retrieve just any group item.
public IGroupItem GetItem(int index)
{
return mItems[index];
}
// This is a method that will get a group item at the specified index
// and then cast it to the specific group item type container.
public GroupItem<T> GetItem<T>(int index)
{
return (GroupItem<T>)mItems[index];
}
}
Here you will be able to build and maintain a single collection that can contain any GroupItem with any Type. So you could have a GroupItems collection that contains items of GroupItem<DateTime>, GroupItem<int>, etc.
Please note that none of these code examples take into account any erroneous circumstances.
Consider: you have a collection of items; the items may have any runtime type (string, int, etc.). Because of this, the static type of the collections items must be object.
It seems that you want to be able to retrieve items from the list with strong static typing. That's not possible without a lot of conditional logic (or reflection). For example:
object item = collection[0];
if (item is int)
//do something with an int
else if (item is string)
//do something with a string
Now suppose instead of "doing something" with the value of collection[0], we assign the value to a variable. We can do one of two things:
use the same variable for both cases, in which case the static type must be object.
use separate variables, in which case the static type will be string or int, but outside of the conditional logic, we can't know which variable holds the value of collection[0].
Neither option really solves the problem.
By creating GroupItem<T>, you add a level of indirection to this problem, but the underlying problem is still there. As an exercise, try reworking the example, but starting from "Consider: you have a collection of items; the items are of type GroupItem<T> where T may be any runtime type (string, int, etc.)."
Thanks for your inputs.
I have resolved it myself using multiple overloading methods to resolve this.
for example:
private void Print(GroupItem<string> items)
{
///custom coding
}
private void Print(GroupItem<int> items)
{
///custom coding
}
Though its not efficient enough, i want to do in this way as it was .net 2.0.
I'm now improving this in .Net 4.0 with new algorithm.
Thanks a lot for all of your helps.
When is it acceptable for an indexer to automatically add items to a collection/dictionary? Is this reasonable, or contrary to best practices?
public class I { /* snip */ }
public class D : Dictionary<string, I>
{
public I this[string name]
{
get
{
I item;
if (!this.TryGetValue(name, out item))
{
item = new I();
this.Add(name, item);
}
return item;
}
}
}
Sample of how this may be used in a collection:
public class I
{
public I(string name) {/* snip */}
public string Name { get; private set; }
/* snip */
}
public class C : Collection<I>
{
private Dictionary<string, I> nameIndex = new Dictionary<string, I>();
public I this[string name]
{
get
{
I item;
if (!nameIndex.TryGetValue(name, out item))
{
item = new I(name);
this.Add(item); // Will also add the item to nameIndex
}
return item;
}
}
//// Snip: code that manages nameIndex
// protected override void ClearItems()
// protected override void InsertItem(int index, I item)
// protected override void RemoveItem(int index)
// protected override void SetItem(int index, I item)
}
There's two problems that you should consider - both of which suggest this is a bad idea.
First, inheriting from the .NET BCL collection types is not generally a good idea. The main reason for this is that most methods on those types (like Add and Remove) are not virtual - and if you provide your own implementations in a derived class, they will not get called if you pass your collection around as the base type. In your case, by hiding the Dictionary<TK,TV> indexer property, you are creating a situation where a call using a base-class reference will do something different than a call using a derived-class reference ... a violation of the Liskov Substitution Principle:
var derived = new D();
var firstItem = derived["puppy"]; // adds the puppy entry
var base = (Dictionary<string,I>)derived;
var secondItem = base["kitten"]; // kitten WAS NOT added .. BAD!
Second, and more importantly, creating an indexer that inserts an item when you attempt to find one is entirely unexpected. Indexers have clearly defined get and set operations - implementing the get operation to modify the collection is very bad.
For the case you describe, you're much better off creating an extension method that can operate on any dictionary. Such an operation is both less surprising in what it does, and also doesn't require creating a derived collection type:
public static class DictionaryExtensions
{
public static TValue FindOrAdd<TKey,TValue>(
this IDictionary<TKey,TValue> dictionary, TKey key, TValue value )
where TValue : new()
{
TValue value;
if (!this.TryGetValue(key, out value))
{
value = new TValue();
this.Add(key, value);
}
return value;
}
}
With no other information about what you're doing, that looks like surprising behavior to me. I hope that you make it very clear from the context (i.e. name it an AutoInitializingDictionary or something) what's to be expected.
I would personally prefer to make this a method rather than an indexer; something like D.FindOrCreate. (I have the feeling there's an idiomatic name for a method that does this which I've temporarily forgotten.)
I would say this violates two principles. 1) principle of least surprise. And 2) that getters shouldn't change anything.
I wouldn't expect to add a the pair {"foo", null} if foo doesn't exist in the colleciton.
x = collection["Foo"]
I think it is perfectly fine as long as this behaviour is made perfectly clear. I have 2 decorator classes:
public class DefaultValueDictionary<K, V> : IDictionary<K, V>
{
public DefaultValueDictionary(IDictionary<K, V> baseDictionary, Func<K, V> defaultValueFunc)
{
...
}
}
and
public class ParameterlessCtorDefaultValueDictionary<K, V>
: DefaultValueDictionary<K, V> where V : new()
{
public ParameterlessCtorDefaultValueDictionary(IDictionary<K, V> baseDictionary)
: base(baseDictionary, k => new V())
{
...
}
}
The second class is perfect for counters and patterns like IDictionary<K,List<V>>;
I can do
var dict = new ParameterlessCtorDefaultValueDictionary<string, int>();
...
dict[key]++;
instead of the laborious:
int count;
if(!dict.TryGetValue(key, out count))
dict[count] = 1;
else dict[count] = count + 1;
The primary reason I would be concerned is that it wouldn't be thread-safe. Multiple readers all attempting to possibly write to the Dictionary at once would require careful lock management that you wouldn't likely think of (or get right) at first.
When is it acceptable for an indexer
to automatically add items to a
collection/dictionary?
Never
Is this reasonable, or contrary to
best practices?
Contrary to best practices
That said, if the class is named appropriately, it'd be acceptable. I'd personally use GetOrAdd instead.
I'd like to have a class "A" with a (for example) SortedList collection "SrtdLst" property, and inside this class "A" allow the addition or subtraction of "SrtdLst" items. But in a instance of the class "A", only allow to get or set the content of the items, not to add new items or subtract the existing ones. In code:
class A
{
public SortedList<string, string> SrtdLst = new SortedList<string, string>();
public A()
{
// This must work:
SrtdLst.Add("KeyA", "ValueA");
// This too:
SrtdLst["KeyA"] = "ValueAAA";
}
}
class B
{
public A a = new A();
public B()
{
// I want the following code to fail:
a.SrtdLst.Add("KeyB", "ValueB");
// But this must work:
a.SrtdLst["KeyA"] = "ValueBBB";
}
}
UPDATE: I want to create a class like System.Data.SqlClient.SqlCommand. For the Stored Procedures you can use the member "DeriveParameters" that fills a collection of "Parameters", so only the value of each item can be modified.
How can this be done?
If you want to ban the modifying operations at compile time, you need a type-safe solution.
Declare an interface for the publicly allowed operations. Use that interface as the property type.
public interface IReadOnlyList<T>
{
T this[int index] { get; }
int Count { get; }
}
Then declare a class that implements that interface and inherits from the standard collection class.
public class SafeList<T> : List<T>, IReadOnlyList<T> { }
Assuming you get the interface definition right, you won't need to implement anything by hand, as the base class already provides the implementations.
Use that derived class as the type of the field that stores the property value.
public class A
{
private SafeList<string> _list = new SafeList<string>();
public IReadOnlyList<string>
{
get { return _list; }
}
}
Within class A, you can use _list directly, and so modify the contents. Clients of class A will only be able to use the subset of operations available via IReadOnlyList<T>.
For your example, you're using SortedList instead of List, so the interface probably needs to be
public interface IReadOnlyDictionary<K, V> : IEnumerable<KeyValuePair<K, V>>
{
V this[K index] { get; }
}
I've made it inherit IEnumerable as well, which is readonly anyway, so is perfectly safe. The safe class would then be:
public class SafeSortedList<K, V> : SortedList<K, V>, IReadOnlyDictionary<K, V> { }
But otherwise it's the same idea.
Update: just noticed that (for some reason I can't fathom) you don't want to ban modifying operations - you just want to ban SOME modifying operations. Very strange, but it's still the same solution. Whatever operations you want to allow, "open them up" in the interface:
public interface IReadOnlyDictionary<K, V> : IEnumerable<KeyValuePair<K, V>>
{
V this[K index] { get; set; }
}
Of course, that's the wrong name for the interface now... why on earth would you want to ban adding via Add but not ban it via the indexer? (The indexer can be used to add items, just as the Add method can.)
Update
From your comment I think you mean that you want to allow assignment to the value of an existing key/value pair, but disallow assignment to a previously unknown key. Obviously as keys are specified at runtime by strings, there's no way to catch that at compile time. So you may as well go for runtime checking:
public class FixedSizeDictionaryWrapper<TKey, TValue> : IDictionary<TKey, TValue>
{
IDictionary<TKey, TValue> _realDictionary;
public FixedSizeDictionaryWrapper(IDictionary<TKey, TValue> realDictionary)
{
_realDictionary = realDictionary;
}
public TValue this[TKey key]
{
get { return _realDictionary[key]; }
set
{
if (!_realDictionary.Contains(key))
throw new InvalidOperationException();
_realDictionary[key] = value;
}
}
// Implement Add so it always throws InvalidOperationException
// implement all other dictionary methods to forward onto _realDictionary
}
Any time you have an ordinary dictionary and you want to hand it to some method that you don't trust to update the existing values, wrap it in one of these.
EDIT: Original answer is below. As earwicker points out, I hadn't noticed that you aren't asking for it to be readonly - just to prevent the Add operation. That doesn't sound like a good idea to me, as the only difference between Add and the indexer-setter is that Add throws an exception if the element is already present. That could easily be faked up by the caller anyway.
Why do you want to restrict just that one operation?
Original answer
For one thing, don't use public fields. That's a surefire way to run into problems.
It looks like you want a read-only wrapper class round an arbitrary IDictionary. You can then have a public property which returns the wrapper, while you access the private variable from within your class. For example:
class A
{
private SortedList<string, string> sortedList = new SortedList<string, string>();
public IDictionary<string, string> SortedList
{
get { return new ReadOnlyDictionaryWrapper(sortedList);
}
public A()
{
sortedList.Add("KeyA", "ValueA");
sortedList["KeyA"] = "ValueAAA";
}
}
Now you've just got to find a ReadOnlyDictionary implementation... I can't implement it right now, but I'll be back later if necessary...
Just make the list private, and expose it as an indexer:
class A {
private SortedList<string, string> _list;
public A() {
_list = new SortedList<string, string>()
}
public string this[string key] {
get {
return _list[key];
}
set {
_list[key] = value;
}
}
}
Now you can only access the items using the index:
a["KeyA"] = "ValueBBB";
However, as the indexer of the list allows creation of new items, you would have to add code in the indexer to prevent that if you don't want that do be possible.
If the keys are known outside of the class then you can add a ChangeItem(key, newValue) and ReadItem(key) to your wrapper class. Then keep the SortedList private to the class.