rbulph Posted September 5, 2006 Posted September 5, 2006 (edited) The IDE tells me that, in the constructor of an inheriting class, calls to MyBase.New must be the first line. This leads to me writing code like: Inherits System.ComponentModel.CategoryAttribute Public Sub New(ByVal x as long) MyBase.New(IIf(x=1, "One", "Two")) End Sub With more complicated conditions you can imagine that the IIfs are going to get ridiculous. Why will it not just let me write: Inherits System.ComponentModel.CategoryAttribute Public Sub New(ByVal x as long) Dim s as string If x= 1 then s="One" Else s="Two" End If MyBase.New(s) End Sub And is there a solution to the problem? Edit: OK, I see that I can call a function in the parameter of MyBase.New, and as long as this function isn't in the inheriting class, it will work OK. So I can manage. Still, any comments welcome. Edited September 5, 2006 by rbulph Quote
Administrators PlausiblyDamp Posted September 5, 2006 Administrators Posted September 5, 2006 In the constructor of the derived class you could be calling functionality or accessing members declared in the base class(es), the base constructors need to be run before any code in the derived class' constructor to ensure that this underlying code is in a consistent and initalised state. If you are doing lots of complex work then perhaps a constructor isn't the best choice and you might need to consider an alternative method. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
Leaders snarfblam Posted September 5, 2006 Leaders Posted September 5, 2006 The next question, I would imagine, would be "What alternatives are there to a constructor?" so I'll offer a couple. Both alternatives are seen from time in the .Net framework, though the first is encountered more often. Neither example does something you can't do with a normal constructor, but they demonstrate alternatives that don't have the same restrictions and can be more straightforward in certain cases. One option is to have no public constructors and instead provide a static method that can be used to obtain instances. This allows you to apply logic before you call a constructor. Class ExampleClass ' Private constructor, only methods defined in this class can instantiate this class. Private Sub New (int v) Base.New(v) End Sub ' This is the function that must be called to get an instance of this class Public Sub GetInstance(numericValue As Integer) ' You can place logic here before creating the object, for example ' confirm that a value is positive before passing it on to the base ' constructor If numericValue < 0 Throw New ArgumentException("The value must be positive.") Return New ExampleClass(numericValue) End Sub End Class The other option is to use a creation-parameters class, where instead of passing a number of parameters to a constructor which needs to process the parameters before calling the base constructor, you create a creation-parameter object, assign values to it, process logic internally in the creation-parameter object, and then finally pass that object as the sole parameter to the constructor of the object you want to instantiate. 'We want to create an ExampleClass object. To do so, we must create a CreateParams 'object, assign data to it, and pass it to an ExampleClass constructor. Class CreateParams 'We can use properties now, instead of constructor parameters Dim _examplePropertyBackingField As Integer Public Property ExampleProperty As Integer Get Return _examplePropertyBackingField End Get Set ' Pre-process you creation parameters here, before we even invoke the ' ExampleClass constructor. If value < 0 Throw New ArgumentException ("Value must be positive.") _examplePropertyBackingField = value End Set End Property End Class Class ExampleClass { Public Sub New(cp As CreationParams) ' Now we don't need to do any processing here because it was already done in ' the CreationParams object. Base.New(cp.ExampleProperty) End Sub End Class Hope that helps. Quote [sIGPIC]e[/sIGPIC]
rbulph Posted September 6, 2006 Author Posted September 6, 2006 Thanks. What I'm trying to achieve is a CategoryAttribute that can only have certain string values for the category. Doing that allows me to select from a choice of categories (through the Intellisense) when I create a new property, rather than having to type in the text of the category each time (and risk getting it slightly different, and so inadvertently creating a new category). The difficulty is that there isn't anywhere to set properties of the CategoryAttribute other than through the constructor since you have to create it as part of the declaration of the property. There is no "room" to follow either of your suggestions, marble-eater. As I say, I have managed to do this to my satisfaction, and I've used code as follows: <CustomCategory(CatTypes.WeatherDetails)> Public Property Get Rainfall as decimal 'Get, Set etc. End Property <AttributeUsage(AttributeTargets.Property, AllowMultiple:=False)> Public Class CustomCategory Inherits CategoryAttribute Public Sub New(ByVal c As CatType) MyBase.New(CatDesc(c)) End Sub End Class Public Module Module1 Public Enum CatTypes WeatherDetails TaxDetails CityDetails End Enum Public Function CatDesc(ByVal ct As CatTypes) As String Select Case ct Case CatTypes.WeatherDetails Return "Weather Info" Case CatTypes.TaxDetails Return "Tax" Case CatTypes.CityDetails Return "Cities" End Select End Function End Module P.S. how do you get code to come out in colours as in marble-eater's post? I'm using the code tags, and you can see the result isn't as good. Quote
Cags Posted September 6, 2006 Posted September 6, 2006 You get the syntax highlighting by using the vb tags instead of code tags. The code tags are a generic way of wrapping code regardless of the language. Using the vb tags or cs tags will highlight a specific language. What I generally do in the situation you described is have a protected method that contains the code I would normal put in the constructor. Then have the child class call this at whatever point it needs to. Heres a little example. Public Class Parent ' Protected Sub Init() ' have constuctor stuff here End Sub ' End Class ' Public Class Child Inherits Parent ' Public Sub New() ' set some properties as required here.... ' then call init method Init() End Sub ' End Class Quote Anybody looking for a graduate programmer (Midlands, England)?
rbulph Posted September 6, 2006 Author Posted September 6, 2006 You get the syntax highlighting by using the vb tags instead of code tags. The code tags are a generic way of wrapping code regardless of the language. Using the vb tags or cs tags will highlight a specific language. What I generally do in the situation you described is have a protected method that contains the code I would normal put in the constructor. Then have the child class call this at whatever point it needs to. Heres a little example. Public Class Parent ' Protected Sub Init() ' have constuctor stuff here End Sub ' End Class ' Public Class Child Inherits Parent ' Public Sub New() ' set some properties as required here.... ' then call init method Init() End Sub ' End Class Yes, except I can't do that here because the CategoryAttribute class is part of System.ComponentModel and is not something that I created. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.