On nondefault indexed properties
-
I'm just looking to get the general TDWTF opinion on non-default indexed properties in VB.NET.
For those not blessed enough to work with VB.NET, I'll summarize. In your classes, you can define properties that take arguments, like so:
which you could then call like this:Public Class MyClass Public ReadOnly Property IndexedProp(ByVal someArg As String) As Object Get Return someArg & "!" End Get End Property End Class
Dim mc As New MyClass() mc.IndexedProp("Hi there") 'Returns "Hi there!"
C# also has these, but you are restricted to a "default" indexed property, with which you can use array subscript notation:
public class MyClass { public string this[string arg] { get { return arg + "!"; } } }
MyClass mc = new MyClass();
string result = mc["Hi"]; //returns "Hi!"
My question is, apart from operations that do act, conceptually, as a kind of index, is there any good use for indexed properties? I got thinking about it because I recently found, in my codebase, the following property:
Public ReadOnly Property ComponentList( _ Optional ByVal filter As ListOfThings.Filters = ListOfThings.Filters.ActiveOnly _ , Optional ByVal parent_id As Integer = Null.IntegerNull _ ) As ListOfThings Get If _fullList Is Nothing Then _fullList = GetTheFullList() End If
' Create filtered copy if necessary Dim listCopy As ListOfThings If filter = ListOfThings.Filters.NoFilter Then listCopy = _fullList Else listCopy = New ListOfThings(_fullList, filter, parent_id) End If Return listCopy End Get End Property
Am I alone in thinking that that should really be a
GetFilteredListOfThings(filter)
method, or something like that, rather than a property?
-
@toth said:
My question is, apart from operations that do act, conceptually, as a kind of index, is there any good use for indexed properties?
-
@Weng said:
@toth said:
My question is, apart from operations that do act, conceptually, as a kind of index, is there any good use for indexed properties?
Well, VB.NET also uses array notation, it's just that VB.NET is stupid enough to use function argument notation for arrays.
But I guess you're referring to C# forbidding the use of indexed properties except as class indexers. I agree that that restriction makes sense, but I wouldn't be that opposed to having a named indexed property, as in VB.NET, as long as it actually uses an "index". Then again, I guess you could just make that property a list/dictionary and have the indexing come for free...
-
The usage that you're pointing to is clearly off (it's a property wrapping two functions), but there is a (quasi) legitimate use I can think of. I'll use C# syntax.
// exposing an property with a default indexer
private IList<string> _aliases = new List<string>{ "alex", "alexander", "alexp" };
public IList<string> Aliases { get { return _aliases; } }// using a property with an indexer
private IList<string> _aliases = new List<string>{ "alex", "alexander", "alexp" };
public string Aliases[int idx] = { get { return _aliases[idx]; } }The usage is basically the same (Aliases[0] vs Aliases[0]) but in the first example you're returning an object and then indexing that object to get the value, whereas the latter simply returns the desired value. The difference is subtle.
theObject.Aliases.Add( "jerkoff"); // possible in the first, since it's an IList<T>
foreach(string s in theObject.Aliases) // not possible in the second, since it's a string
Yes, you just use functions - but then again, you could say the same about normal properties. I think they don't include these in C# because they're really easy to abuse... as you've seen first hand... and they don't add enough value to risk the abuse. The same can be said about rocket launchers.
-
@Alex Papadimoulis said:
// exposing an property with a default indexer
private IList<string> _aliases = new List<string>{ "alex", "alexander", "alexp" };
public IList<string> Aliases { get { return _aliases; } }// using a property with an indexer
private IList<string> _aliases = new List<string>{ "alex", "alexander", "alexp" };
public string Aliases[int idx] = { get { return _aliases[idx]; } }The usage is basically the same (Aliases[0] vs Aliases[0]) but in the first example you're returning an object and then indexing that object to get the value, whereas the latter simply returns the desired value. The difference is subtle.
I see your point, but I have trouble imagining a situation in which not allowing consumers of the class to treat the property as a collection except for indexing would be a particularly desirable feature. Is there a good reason why you would want to make
foreach(string s in theObject.Aliases)
not work?@Alex Papadimoulis said:
The same can be said about rocket launchers.
Yeah, except parameterized properties are dangerous. Rocket launchers are just fun.
-
@toth said:
I see your point, but I have trouble imagining a situation in which not allowing consumers of the class to treat the property as a collection except for indexing would be a particularly desirable feature. Is there a good reason why you would want to make
foreach(string s in theObject.Aliases)
not work?
The standard C answer - indexed properties are lighter weight than properties that implement IEnumerable, while still exposing a property-like interface. Another really edge-case scenario would be if you wanted to expose the elements of the same collection through two properties (maybe you need to implement two interfaces) and enumerating wasn't important.
At the end of the day properties are simply syntactic sugar on top of methods, so any discussion of indexed property vs. method would have to come down to readability, not functionality.
-
@Alex Papadimoulis said:
theObject.Aliases.Add( "jerkoff"); // possible in the first, since it's an IList<T>
foreach(string s in theObject.Aliases) // not possible in the second, since it's a string
If you're maintaining the integrity of the data, you should be returning a copy of the list already, or a read-only list. I also don't see any reason to make this a property and not a method.
@Jaime said:
The standard C answer - indexed properties are lighter weight than properties that implement IEnumerable
How so? I'd guess it likely doesn't apply to managed languages.