|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
HashTable.Add Modifies HashTable Items?(Generic.List) in the application-scope as a HashTable (a make-shift cache), indexed by an Enum value - i.e., CType(Application.Item("SysTables"), HashTable).Add(DataAttribute.Database.Recruiting, TableList). The Enum values are as follows: Enum DataAttribute.Database Data = 0 DataAccess = 1 EventLog = 2 Recruiting = 3 End Enum I load each of the collections using a method that I call with each of the four Enum values. Each collection contains a List of a class called SystemTable that, among other things, contains a property called "Database" - a DataAttribute.Database Enum value, like so: Public Property Database() As DataAttribute.Database Get Return InDatabase End Get Set(ByVal Value As DataAttribute.Database) InDatabase = Value End Set End Property As I load each collection into the application-scope HashTable, the previously-added HashTable items are being modified. For instance, let's say that the first collection I add is CType(Application.Item("SysTables"), HashTable).Add(DataAttribute.Database.Data, TableList), where each SystemTable in TableList has a "Database" property value of "Data." When I add the second item (CType(Application.Item("SysTables"), HashTable).Add(DataAttribute.Database.DataAccess, TableList)), I find that each one of my SystemTable instances in the first item (Data) now have a "Database" property value of "DataAccess." How in the world is the .Add method on HashTable modifying a single property value of each of the members of an item contained in the collection? Why isn't it changing the "ID" property or the "Name" property? Since when does the .Add property modify existing members anyway? This test code works, and it's nearly identical to the code I'm running
in my Web app (aside from the obvious complexity of loading a class from a database, etc.): Module Module1 Private _dictionary As New Dictionary(Of Class1.DatabaseEnum, List(Of Class1)) Sub Main() _dictionary.Add(Class1.DatabaseEnum.Data, GetCollection(Class1.DatabaseEnum.Data)) _dictionary.Add(Class1.DatabaseEnum.DataAccess, GetCollection(Class1.DatabaseEnum.DataAccess)) _dictionary.Add(Class1.DatabaseEnum.EventHistory, GetCollection(Class1.DatabaseEnum.EventHistory)) _dictionary.Add(Class1.DatabaseEnum.Recruiting, GetCollection(Class1.DatabaseEnum.Recruiting)) End Sub Private Function GetCollection(ByVal InDatabase As Class1.DatabaseEnum) As List(Of Class1) Dim ClassList As New List(Of Class1) For count As Integer = 0 To 9 ClassList.Add(New Class1(InDatabase)) Next Return ClassList End Function End Module I don't know if anybody cares at this point or not, but here's the
solution to the Enum problem (note that it's an Enum problem and not a HashTable or Dictionary problem). Enums cannot be used as Shared members of a base class. There's no documentation to support this, but here's what I found: when I use an Enum as a Shared member of a base class, the last value populated in the base class is the value returned from all subclasses. That means whenever I instantiate a new subclass and I give it a new value for the Enum member, all previously instantiated subclasses now return the new value when accessed. First of all, WTF? Second, what is the thinking behind this? My Shared String and Integer members don't change their values when a new subclass is instantiated. An Enum is a structure and not a type, but why would that mean that an instance of an Enum can only hold a single value across the entire application? Weird. CoderHead wrote:
Show quote > I don't know if anybody cares at this point or not, but here's the CoderHead,> solution to the Enum problem (note that it's an Enum problem and not a > HashTable or Dictionary problem). > > Enums cannot be used as Shared members of a base class. There's no > documentation to support this, but here's what I found: when I use an > Enum as a Shared member of a base class, the last value populated in > the base class is the value returned from all subclasses. That means > whenever I instantiate a new subclass and I give it a new value for the > Enum member, all previously instantiated subclasses now return the new > value when accessed. First of all, WTF? Second, what is the thinking > behind this? My Shared String and Integer members don't change their > values when a new subclass is instantiated. An Enum is a structure and > not a type, but why would that mean that an instance of an Enum can > only hold a single value across the entire application? Weird. That's the behavior I would expect from a Shared (static) class member. If you want each instance of the class to have its own value then don't modify the variable using the 'Shared' keyword. Also, can you post a short, but complete program demonstrating that shared (static) string and integer members behave differently than enums? Brian I learned something today. A Shared member in a base class is shared
only to identical instances of the derived class. So if I have Class1 and Class2 that derive from BaseClass, instantiating Class2 won't affect the Shared members of Class1. For example: --------------------------------------------------------- Module Module1 Sub Main() Dim MyClasses As New Collection() MyClasses.Add(New Class1(AttributeClass.Test.One, "First Try", 100)) Console.WriteLine("Before MyClasses(1), MyClasses(0) = " & MyClasses.Item(1).ToString()) MyClasses.Add(New Class2(AttributeClass.Test.Two, "Second Try", 200)) Console.WriteLine("MyClasses(0) = " & MyClasses.Item(1).ToString()) Console.WriteLine("MyClasses(1) = " & MyClasses.Item(2).ToString()) End Sub End Module --------------------------------------------------------- <AttributeUsage(AttributeTargets.Class)> Public Class AttributeClass Inherits Attribute Enum Test One = 1 Two = 2 End Enum Public EnumVar As Test = Test.One Public StringVar As String = String.Empty Public IntegerVar As Integer = 0 Public Sub New(ByVal EnumValue As Test, ByVal StringValue As String, ByVal IntegerValue As Integer) EnumVar = EnumValue StringVar = StringValue IntegerVar = IntegerValue End Sub End Class --------------------------------------------------------- Public Class BaseClass(Of t) Protected Shared EnumVar As AttributeClass.Test = AttributeClass.Test.One Public Shared StringVar As String = String.Empty Public Shared IntegerVar As Integer = 0 Shared Sub New() For Each Attr As Attribute In GetType(t).GetCustomAttributes(True) If TypeOf Attr Is AttributeClass Then EnumVar = CType(Attr, AttributeClass).EnumVar StringVar = CType(Attr, AttributeClass).StringVar IntegerVar = CType(Attr, AttributeClass).IntegerVar End If Next End Sub Public Sub New() End Sub Public Sub New(ByVal EnumValue As AttributeClass.Test, ByVal StringValue As String, ByVal IntegerValue As Integer) EnumVar = EnumValue StringVar = StringValue IntegerVar = IntegerValue End Sub Public Overrides Function ToString() As String Return GetType(t).Name & ", EnumVar=" & EnumVar & ", StringVar='" & StringVar & "', IntegerVar=" & IntegerVar.ToString() End Function End Class --------------------------------------------------------- <AttributeClass(AttributeClass.Test.One, "Class1", 999)> Public Class Class1 Inherits BaseClass(Of Class1) Public Sub New() MyBase.New() End Sub Public Sub New(ByVal EnumValue As AttributeClass.Test, ByVal StringValue As String, ByVal IntegerValue As Integer) MyBase.New(EnumValue, StringValue, IntegerValue) End Sub End Class --------------------------------------------------------- <AttributeClass(AttributeClass.Test.Two, "Class2", 888)> Public Class Class2 Inherits BaseClass(Of Class2) Public Sub New() MyBase.New() End Sub Public Sub New(ByVal EnumValue As AttributeClass.Test, ByVal StringValue As String, ByVal IntegerValue As Integer) MyBase.New(EnumValue, StringValue, IntegerValue) End Sub End Class That explains why my other classes and other properties weren't being affected. Because the only property I happened to be changing was the Enum value. CoderHead <coderh***@gmail.com> wrote:
Show quote > I don't know if anybody cares at this point or not, but here's the There's nothing weird about the enum, but I believe you're entirely > solution to the Enum problem (note that it's an Enum problem and not a > HashTable or Dictionary problem). > > Enums cannot be used as Shared members of a base class. There's no > documentation to support this, but here's what I found: when I use an > Enum as a Shared member of a base class, the last value populated in > the base class is the value returned from all subclasses. That means > whenever I instantiate a new subclass and I give it a new value for the > Enum member, all previously instantiated subclasses now return the new > value when accessed. First of all, WTF? Second, what is the thinking > behind this? My Shared String and Integer members don't change their > values when a new subclass is instantiated. An Enum is a structure and > not a type, but why would that mean that an instance of an Enum can > only hold a single value across the entire application? Weird. mistaken about your String and Integer members. There's only *one* copy of any particular Shared variable for the entire AppDomain. Different subclasses don't get extra copies. The variable is associated with the type it's declared in. -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too I am admittedly mistaken about the String and Integer values, but I
believe you're mistaken about derived classes. Run the sample code I attached a little while ago and you'll see that although Class1 and Class2 are in the same AppDomain, they receive different copies of the shared member variables. The proof is that I instantiate Class2 with different values than Class1 but they both write their disparate values to the Console. Don't believe me? Check it out. That's why this thing has been confusing for me. Jon wrote: Show quote > There's nothing weird about the enum, but I believe you're entirely > mistaken about your String and Integer members. > > There's only *one* copy of any particular Shared variable for the > entire AppDomain. Different subclasses don't get extra copies. The > variable is associated with the type it's declared in. > -- > Jon Skeet - <sk***@pobox.com> CoderHead <coderh***@gmail.com> wrote:
> I am admittedly mistaken about the String and Integer values, but I Well, they have different base types effectively - one is > believe you're mistaken about derived classes. Run the sample code I > attached a little while ago and you'll see that although Class1 and > Class2 are in the same AppDomain, they receive different copies of the > shared member variables. BaseClass(Of Class1) and the other is BaseClass(Of Class2). I had indeed neglected to take account of generics, but that's why you're seeing the different values - it has nothing to do with subclasses really. Basically, BaseClass(Of Class1) has one set of static (shared) variables, and BaseClass(Of Class2) has another set. They're different types. Here's an example (in C#) demonstrating that: using System; class Counter { static int next=0; public static int Next { get { return next++; } } } class Foo<T> { public static int x = Counter.Next; } class Test { static void Main() { Console.WriteLine (Foo<int>.x); Console.WriteLine (Foo<string>.x); Console.WriteLine (Foo<long>.x); Console.WriteLine (Foo<char>.x); } } Now, if you had a different subclass which still had the same base class as one of the others, eg: Public Class Class3 Inherits BaseClass(Of Class1) then you'd see the shared variables being shared, because they both genuinely have the same base class. -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too Jon Skeet [ C# MVP ] wrote:
Show quote > CoderHead <coderh***@gmail.com> wrote: Thanks for clearing that up, that actually helps me.> > I am admittedly mistaken about the String and Integer values, but I > > believe you're mistaken about derived classes. Run the sample code I > > attached a little while ago and you'll see that although Class1 and > > Class2 are in the same AppDomain, they receive different copies of the > > shared member variables. > > Well, they have different base types effectively - one is > BaseClass(Of Class1) and the other is BaseClass(Of Class2). > > I had indeed neglected to take account of generics, but that's why > you're seeing the different values - it has nothing to do with > subclasses really. Basically, BaseClass(Of Class1) has one set of > static (shared) variables, and BaseClass(Of Class2) has another set. > They're different types. Here's an example (in C#) demonstrating that: > > using System; > > class Counter > { > static int next=0; > > public static int Next > { > get > { > return next++; > } > } > } > > class Foo<T> > { > public static int x = Counter.Next; > } > > class Test > { > static void Main() > { > Console.WriteLine (Foo<int>.x); > Console.WriteLine (Foo<string>.x); > Console.WriteLine (Foo<long>.x); > Console.WriteLine (Foo<char>.x); > } > } > > Now, if you had a different subclass which still had the same base > class as one of the others, eg: > > Public Class Class3 Inherits BaseClass(Of Class1) > > then you'd see the shared variables being shared, because they both > genuinely have the same base class. > > -- > Jon Skeet - <sk***@pobox.com> > http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet > If replying to the group, please do not mail me too |
|||||||||||||||||||||||