简体   繁体   中英

C# determining object type of list item

I'm trying to do a project for my C# class that adds students from either Student object(parent) or DormStudent(child) into a List that is set up for Student objects. I need to read in an object based on student ID and determine if its a student or dorm student and fill out the rest of the form accordingly.

    int pos = MainMenu.myList.FindIndex(x => x.ID == validID);
    if (MainMenu.myList[pos] == Student)
    {
        Student tempStu = MainMenu.myList[pos];
        nameTextBox.Text = tempStu.Name;
    }
    else
    {
        DormStudent tempDorm = MainMenu.myList[pos];
        dormCheckBox.Checked = true;
        dormTextBox.Text = tempDorm.Dorm;
        if (tempDorm.MealType == "B")
        {
            basicRadioButton.Checked = true;
        }
        else if (tempDorm.MealType == "M")
        {
            mediumRadioButton.Checked = true;
        }
        else
        {
            highRadioButton.Checked = true;
        }
    }

here is the list and object items

    public static List<Student> myList = new List<Student>();

    [Serializable]
    public class DormStudent : Student
    {
        public string Dorm{get; set;}
        public string MealType { get; set; }
        public DormStudent() : base()
        {
            Dorm = "No Dorm";
            MealType = "B";
        }
        public DormStudent(int i, string n, string d, string m) : base(i, n)
        {
            Dorm = d;
            MealType = m;
        }
    }

    [Serializable]
    public class Student
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public List<int> Grades;
        public Student()
        {
            ID = 0;
            Name = "No Student";
            Grades = new List<int>();
        }
        public Student(int i, string n)
        {
            ID = i;
            Name = n;
        }
    }

To determine if an object is of a particular type, use the is operator.

ie.

if (MainMenu.myList[pos] is Student)
{
    ...
}
else if (MainMenu.myList[pos] is DormStudent)
{
    ...
}

Now, in this particular case that won't work since the way I wrote code above will catch both types in the first clause since DormStudent inherits from Student .

To handle this, reverse the checks:

if (MainMenu.myList[pos] is DormStudent)
{
    ...
}
else if (MainMenu.myList[pos] is Student)
{
    ...
}

This still has the problem that if any other type that inherits from DormStudent or Student comes along it will be caught by the above if-statements. If you don't want that, here's how to only identify the known types:

if (MainMenu.myList[pos].GetType() == typeof(DormStudent))
{
    ...
}
else if (MainMenu.myList[pos].GetType() == typeof(Student))
{
    ...
}
else
{
    ... // other type?
}

Since DormStudend is derived from student, you need to ask whether the object is a DormStudent first. (The usual from specific to general approach)

So you need to swap your If-Statement like this:

if(MainMenu.myList[pos] is DormStudent)
{
  ...
}
else
{
   ...
}

Reply to your comment: You can use the as keyword instead to make it abit easier. as is basically a 'try cast' It will return the casted object or null if it cannot cast.

Student student = MainMenu.myList[pos];
DormStudent dormStudent = student as DormStudent;

if(dormStudent!= null)
{
     dormTextBox.Text = dormStudent.Dorm;
}
else
{
    nameTextBox.Text = student.Name;
}

I leave the comments on whether this design is optimal to others, but what you're looking for is the is operator keyword.

var someStudent = MainMenu.myList[pos];
//Check for null here
if (someStudent is DormStudent )
{
    DormStudent tempDorm = someStudent as DormStudent ;
    dormCheckBox.Checked = true;
    dormTextBox.Text = tempDorm.Dorm;
    if (tempDorm.MealType == "B")
    {
        basicRadioButton.Checked = true;
    }
    else if (tempDorm.MealType == "M")
    {
        mediumRadioButton.Checked = true;
    }
    else
    {
        highRadioButton.Checked = true;
    }
    Student tempStu = someStudent ;
    nameTextBox.Text = tempStu.Name;
}
else
{
    nameTextBox.Text = someStudent.Name;
}

But you can also you as with a null check:

var someStudent = MainMenu.myList[pos];
//Null check here?
var dormStudent = someStudent as DormStudent;
if (dormStudent != null)
{
    DormStudent tempDorm = someStudent as DormStudent ;
    dormCheckBox.Checked = true;
    dormTextBox.Text = dormStudent.Dorm;
    if (dormStudent.MealType == "B")
    {
        basicRadioButton.Checked = true;
    }
    else if (dormStudent.MealType == "M")
    {
        mediumRadioButton.Checked = true;
    }
    else
    {
        highRadioButton.Checked = true;
    }
}
nameTextBox.Text = someStudent.Name;

if (!(MainMenu.myList[pos] is DormStudent))

you need is operator to test the type and test for descendant. You can as well retrive Student from the list and cast it to DormStudent using as operator and check if null.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM