Home > Software design >  VB.NET Class Shared Function or Instance function
VB.NET Class Shared Function or Instance function

Time:02-11

Just wondering what is the best practice when using functions or properties. I have a class

Class Person
    Property FirstName as String
    Property LastName as String

    'code to use
    Return $"{LastName.ToUpper}, {FirstName}"
End Class

What's the best way?

  1. ReadOnly Property FullName as String
  2. Function FullName as String
  3. Shared Function FullName(p as Person) as String

My understanding is 3 would be better as 1 or 2 would be part of the object, but there is nothing unique in what they do to an object, so the same code would be duplicated for every Person object.

CodePudding user response:

At the time of writing this answer, there is a vote to close your question on the basis that it is "likely to be answered with opinions rather than facts and citations". About your 3. this is surely not the case because a shared member alone can only access shared members directly so it is out of the question. As for 1. and 2., this is what they would look like:

Class Person

    Public Property FirstName as String
    Public Property LastName as String

    Public Function GetFullName() As String
        Return $"{LastName.ToUpper}, {FirstName}"
    End Function

    Public ReadOnly Property FullName As String
        Public Get
            Return $"{LastName.ToUpper}, {FirstName}"
        End
    End Property

End Class

Calling them:

Dim p As New Person() With {.FirstName = "John", .LastName = "Doe"}
Console.WriteLine(p.GetFullName())
Console.WriteLine(p.FullName)

DOE, John
DOE, John

Both do the same thing. Here comes the opinion part:

I prefer the property in this case because it doesn't do much work. I expect a method to do a little more work behind the scenes - I wouldn't expect a property to take much time to run, but am ok with a method delaying a bit - but that's a bit subjective. From this answer, "Methods imply doing so action, while properties imply getting some data." with which I agree (also with some other good info in the Q&A).

A way to pigeonhole a shared function into this answer would be to write a function which can be used by the instance members, but it can't access the name properties directly. As for the public API, the question is still between 1. and 2.. It may look something like this

Class Person

    Public Property FirstName As String
    Public Property LastName As String

    Public Function GetFullName() As String
        Return getFullName(FirstName, LastName)
    End Function

    Public ReadOnly Property FullName As String
        Get
            Return getFullName(FirstName, LastName)
        End Get
    End Property

    Private Shared Function getFullName(firstName As String, lastName As String)
        Return $"{lastName.ToUpper}, {firstName}"
    End Function

    Private Shared Function getFullName(p As Person)
        Return $"{p.LastName.ToUpper}, {p.FirstName}"
    End Function

End Class

CodePudding user response:

My understanding is 3 would be better as 1 or 2 would be part of the object, but there is nothing unique in what they do to an object, so the same code would be duplicated for every Person object.

No, code is not duplicated. All object instances of a class contain their own copy of their fields, but there is only one copy of the code in memory.

An instance method can be considered syntactic sugar for a shared method which takes the object instance as its first parameter, so there is no difference between 2 and 3 with respect to memory usage. Option 2 has a few advantages over option 3, though:

  • It's more idiomatic: myPerson.GetFullName() is easier to read than Person.GetFullName(myPerson).
  • It allows you to add polymorphism, if needed: An instance method can be overridden in a subclass, and instance methods can be used to implement interfaces.

A read-only property can be considered syntactic sugar for an instance method, so there's not much difference between 1 and 2 either. Microsoft published a guideline to choose between those two:

In particular, it advises to choose a property if "the member represents a logical attribute of the type", which is the case here. It also lists a number of criteria for choosing a method (expensive operation, conversion, different result on subsequent calls, side effects, state copy), none of which apply here. Thus, I'd say that option 1 is a clear winner here.

  • Related