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:

    
    Public Class MyClass
        Public ReadOnly Property IndexedProp(ByVal someArg As String) As Object
            Get
                Return someArg & "!"
            End Get
        End Property
    End Class
    
    
    which you could then call like this:
    
    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?


  • Garbage Person

    @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?

    No, and that's why the C# version uses array notation.


  • @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?

    No, and that's why the C# version uses array notation.

    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...


  • ♿ (Parody)

    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.


Log in to reply