Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
164 views
in Technique[技术] by (71.8m points)

c# - How to sort through a generic list object

My code is designed to parse an unknown json file using json.net that has nested classes and create checkboxes to easily look through it.

At some point during the parsing it arrives to a List object

I have the type and the actual object

The type has AssemblyQualifiedName "System.Collections.Generic.List`1[[Calibration.Camera, CalibrationOrganizer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

The object is a List<Calibration.Camera>

If I loop through the List this way it works, but the problem is I'm assuming a known data type, which I don't. This is just one of many data types in the json file

if (currentType.Name == "List`1")
{
    for (int i = 0; i < ((List<Calibration.Camera>)currentValue).Count; i++)
    {
        cbox = new CheckBox();
        cbox.Text = "[" + i.ToString() + "]";
        cbox.Name = prev_properties + "!" + curr_property;
        cbox.AutoSize = true;
        cbox.Location = new Point(1100 + prop_list.Count() * 100, i++ * 20); //vertical
        cbox.CheckedChanged += new EventHandler(ck_CheckedChanged);
        this.Controls.Add(cbox);
    }   
}

If I try this, it wont compile

for (int i = 0; i < currentValue.Count; i++) {...}

with error: Operator '<' cannot be applied to operands of type 'int' and 'method group'

If I try this, it crashes

for (int i = 0; i < ((List<object>)currentValue).Count; i++)

with exception: System.InvalidCastException: 'Unable to cast object of type 'System.Collections.Generic.List1[Calibration.Camera]' to type 'System.Collections.Generic.List1[System.Object]'.'

So Im not sure what I can do,

I can parse the AssemblyQualifiedName and get the Object type as a string, but how do I convert it to an object type again?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's a lot simpler if you cast it ahead of time. For example:

if (currentType.Name == "List`1")
{
    var list = currentValue as List<Calibration.Camera>;
    if (list == null) throw new ArgumentException("currentType and currentValue do not match.");
    foreach (var camera in list)
    {
        cbox = new CheckBox
        {
            Text = "[" + i.ToString() + "]",
            Name = prev_properties + "!" + curr_property,
            AutoSize = true,
            Location = new Point(1100 + prop_list.Count() * 100, i++ * 20) //vertical
        };
        cbox.CheckedChanged += new EventHandler(ck_CheckedChanged);
        this.Controls.Add(cbox);               
    }
}

In this example, we "cast" using as and do a null check to ensure it's the right type (you can throw an exception or just skip it silently if you prefer).

If you're not sure it's an actual List<Camera> but you know it's some kind of enumerable, you can cast to a non-generic IEnumerable (not IEnumerable<T>) and then use OfType<> on it. That will extract anything in the list that matches the type you want, and also cast it to a generic/typed IEnumerable<T>, which you can then use ToList() on.

if (currentType.Name == "List`1")
{
    var enumerable = currentValue as IEnumerable;
    if (enumerable == null) throw new ArgumentException("Doesn't seem to be a list.");
    var list = enumerable.OfType<Calibration.Camera>().ToList();
    foreach (var camera in list)
    {
        //etc....

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...