It's probable the question of typization (in C++ with STL everything would be made through std::vector and no questions would appear).
I have an ArrayList and I'd like to store some structs there. Like
struct txtRange
{
public String sText;
public String sTag;
public int iBeg;
public int iEnd;
};
ArrayList Ranges = new ArrayList();
txtRange iRange;
iRange.sText = entityText;
iRange.sTag = "";
iRange.iBeg = Ranges.Count > 0 ? Ranges[Ranges.Count - 1].iEnd + 1 : 0;
iRange.iEnd = iRange.iBeg + tmpstr.Length;
Ranges.Add(iRange);
Actually, I have troubles when accessing Ranges[Ranges.Count - 1].iEnd: 'object' does not contain a definition for 'iEnd'. How should a ArrayList of the type specified be created?
The similar question (How to cast object/structure into arraylist?) made me laugh a bit... But still, there is an explanation how to add structures into ArrayList but not how to get the values 开发者_Go百科from there.
You have three problems here:
You're using mutable structs. That's a bad idea to start with. Why isn't
txtRange
a class?You're using public fields - no encapsulation.
You're using the non-generic
ArrayList
type which means everything is getting boxed and you only have weak typing.
You can cast the result as you remove it, but then if you want to change the contents, you'll have to put it back again (because it's a struct, and is being copied each time). The snippet you've given doesn't actually need to change anything, but you're likely to run into it at some point. Here's the snippet in working code:
txtRange iRange;
iRange.sText = entityText;
iRange.sTag = "";
iRange.iBeg = Ranges.Count > 0 ? ((txtRange) Ranges[Ranges.Count - 1]).iEnd + 1
: 0;
iRange.iEnd = iRange.iBeg + tmpstr.Length;
Ranges.Add(iRange);
However, I would suggest:
- Rename
txtRange
toTextRange
- Use a generic
List<T>
instead ofArrayList
unless somehow you're working on a platform which doesn't support generics (the microframework or .NET 1.1) - Either make
TextRange
immutable, or make it a class - or possibly both - Use properties instead of public fields (see here for more reasons)
- Avoid using abbreviations, and I would personally ditch the "i" prefix (I'd use Start, Tag, End, Text)
As I see it, you just need to cast the output.
((txtRange)Ranges[Ranges.Count-1]).iEnd
Or use List<txtRange>
instead for strongly typed loving.
You need to first cast it to a type of txtRange before you can access its propertys the way you specified.
Or you can always go the List<T>
where t is txtRange route as that will work without casting
iRange.iBeg = Ranges.Count > 0 ? ((txtRange)Ranges[Ranges.Count - 1]).iEnd + 1 : 0;
Thanks, the problem can both be solved by an explicit cast like
iRange.iBeg = Ranges.Count > 0 ? ((txtRange)Ranges[Ranges.Count - 1]).iEnd + 1 : 0;
or by using generics.
精彩评论