Cannot convert from Object[] to String[]
BlitzMax Forums/BlitzMax Programming/Cannot convert from Object[] to String[]
| ||
Strict Local a:Object[3] a[0] = "hi" a[1] = "bye" a[2] = "my" Local s:String[] s = String[](a) For Local b:String = EachIn s Print b Next It displays nothing but if I change a to String[3] it works fine. |
| ||
The strings "hi", "bye", "my" are getting cast down to Objects when you put them in a. Not all objects can be converted to strings, so blitzmax can't assume when it sees an object that it can convert it to a string. Now, the way EachIn works is, it iterates through a load of objects given by the enumerated object (in this case, s). It only operates on the ones which can be converted to the type you want (in this case, String). None of the entries in a can do that, because the program only knows they're Objects at this point, so the Print statement is never even encountered. This behaviour is a bit easier to see with lists: 'create a few different types 'a is the base type Type Ta End Type 'b can be converted to a Type Tb Extends Ta End Type 'c can be converted to a but not to b Type Tc Extends Ta End Type 'make one of each type l:TList = New TList l.addlast (New Ta) l.addlast (New Tb) l.addlast (New Tc) 'now try iterating through the list with variables of different types For a:Ta = EachIn l Print "an object of type a" Next For b:Tb = EachIn l Print "an object of type b" Next For c:Tc = EachIn l Print "an object of type c" Next Now, blitzmax should probably throw an error when you try to do what you did with arrays, because everything in an array is of the same type so nothing will ever be able to be cast to the type you want, but because of the way EachIn is implemented that would be very hard. |
| ||
To be more specific, the problem isn't with the EachIn and that was just to test the result. The problem is the conversion process itself - s is Null. I've casted arrays of different objects before so I was disappointed you can't do this with strings. Here is an example which works. Strict Local a:Object[3] a[0] = TString.Create("hi") a[1] = TString.Create("bye") a[2] = TString.Create("my") Print a.length Local s:TString[] s = TString[](a) Print s.length For Local b:TString = EachIn s Print b.s Next Type TString Field s:String Function Create:TString(a:String) Local ts:TString = New TString ts.s = a Return ts End Function End Type |
| ||
oh! Then I look silly. |
| ||
I have no Idea why the cast from Object[] to String[] is not working, but why would you have to cast the array, if yo can simply doLocal a:Object[3] a[0] = TString.Create("hi") a[1] = TString.Create("bye") a[2] = TString.Create("my") For Local s:String = Eachin a ..? Call me Sherlock if I missed something .. |
| ||
Mmmh, I found a rather strange workaround: If you initialize a with 'New String[3]' it all works: SuperStrict Local a:Object[] = New String[3] a[0] = "hi" a[1] = "bye" a[2] = "my" Local s:String[] = String[](a) For Local b:String = EachIn s Print b Next Edit: If you initialize the object array with 'New String[]' You can even set one of the elements to a custom type object and the Object[]->String[] conversion still works out: SuperStrict Type something Field x:Int End Type Local a:Object[] = New String[4] a[0] = "hi" a[1] = "bye" a[2] = "my" a[3] = New something Local s:String[] = String[](a) For Local b:String = EachIn s Print b Next |
| ||
Ok, so the type-checking must have got too hard, but being able to have an array cast down then up is still useful. Look at this:Type ta End Type Type tb Extends ta Field s$ Function Create:tb(s$) b:tb=New tb b.s=s Return b End Function End Type Type tc End Type Local a:ta[3] a[0]=tb.Create("hi") a[1]=tb.Create("hi") a[2]=New ta Local b:tb[] b=tb[](a) 'allowed, but same problem as with tstring Print b[2].s 'segfault Local c:tc[] c=tc[](a) 'can't convert ta Array to tc Array The problem must be that strings aren't *really* objects. |
| ||
The problem must be that strings aren't *really* objects. So the question must be "Why arent they *really* objects?". Obviously you can convert a string to an Object, right? This is actually the one thing I dont like about BlitzMax; the sacrfice of transparency in favor of simplicity.. |
| ||
The plot thickens! Is this a feature or a bug? The reason why I asked about this is because I am trying to convert a TList of Strings into a String array, using ToArray(), but it's less hassle to convert it myself. |
| ||
I am trying to convert a TList of Strings into a String array, using ToArray() Surprisingly, looking at what the TList.toArray() Method actually does, this doesnt seem like a good idea: Local arr:Object[Count()],i Local link:TLink=_head._succ While link<>_head arr[ i ]=link._value link=link._succ i:+1 Wend Return arr This method iterates the whole list twice; once to count the elements and then to write the actual data. So keep track of the count yourself and avoid using the Count() method too! |
| ||
I noticed that! But it has only a dozen elements at most, so I can live with it for now. |