通用类,其中T:类澄清

时间:2017-04-13 03:14:46

标签: c# generics

我已经彻底阅读了这个问题的半答案,以及MSDN关于泛型类的所有内容,但是当泛型类继承自另一个类时我仍然遇到麻烦:where T: ClassName

例如,这是我的通用列表类

public class MyGenericList2<T> where T : Person
{
    private T[] list;

    public MyGenericList2(int size)
    {
        list = new T[size];
    }

    public T getItem(int index)
    {
        T temp = default(T);
        temp = list[index];
        return temp;
    }

    public void setItem(int index, T value)
    {
        list[index] = value;
    }

    public void DisplayList()
    {
        for (int i = 0; i < list.Length; i++)
        {
            Console.Out.WriteLine(list[i]);
        }
    }
}

它继承自person类: 注意:为了清楚起见,它缩短了

public abstract class Person
{
    protected string firstName;

    // Getters
    public string getFirstName()
    {
        return this.firstName;
    }
    public void setFirstName(string fname)
    {
        this.firstName = fname;
    }
}

当我尝试调用它时,我收到一个关于尝试将字符串转换为{namespace} .Person的错误,我得到的是,我试图将字符串放入“Person”框中,但是如何是否使用此机制调用该类?

这是主要方法

public static void Main(string[] args)
{
    MyGenericList2<Person> studentGeneric = new MyGenericList2<Person>(3);
    Student st1 = new Student();

    st1.setFirstName("Thor");
    studentGeneric.setItem(0, st1); //This does not work
    studentGeneric.setItem(1, Person.setFirstName("Odin"); // Does not work
    studentGeneric.setItem(2, st1.setFirstName("Slepnir"); // Does not work
    studentGeneric.DisplayList();
    Console.ReadLine();
}

如果我删除Where T : Person并使用GenericList2<string>它可以正常工作,这是有道理的,因为它是字符串到字符串。

任何帮助将不胜感激

快速澄清学生继承自人:

public class Student : Person
{

    // Student 1
    private string studentID01 = "001";

    public string getStudentID01()
    {
        return this.studentID01;
    }
}

2 个答案:

答案 0 :(得分:1)

您错误地使用了setItem。此方法可用于在list类的实例中设置MyGenericList2数组中元素的值。

要在Student类的实例上使用setFirstName方法,请先使用getItem返回对象实例。例如:

public void Main(string[] args)
{
    MyGenericList2<Person> studentGeneric = new MyGenericList2<Person>(3);

    Student st1 = new Student();
    st1.setFirstName("Thor");
    studentGeneric.setItem(0, st1);

    Student st2 = new Student();
    studentGeneric.setItem(1, st2);
    studentGeneric.getItem(1).setFirstName("Odin");

    Student st3 = new Student();
    studentGeneric.setItem(2, st3);
    studentGeneric.getItem(2).setFirstName("Slepnir");

    studentGeneric.DisplayList();
    Console.ReadLine();
}

要正确显示列表内容,请将您的DisplayList()方法替换为:

public void DisplayList()
{
    for (int i = 0; i < list.Length; i++)
    {
        if(list[i] != null){
            Console.Out.WriteLine("{0}: {1}", i, list[i].getFirstName());
        }
        else
        {
            Console.Out.WriteLine("{0}: [NULL]", i);
        }
    }
}

答案 1 :(得分:1)

首先,我建议您为类使用公共属性,例如:

public abstract class Person
{
    public string FirstName { get; set; }   
}

public class Student : Person
{
    public string StudentId { get; set; }
}

这意味着您的列表代码将如下所示:

Student st1 = new Student();
st1.FirstName = "Thor";
studentGeneric.setItem(0, st1);

你甚至可以使用这种语法:

studentGeneric.setItem(1, new Student
{
    FirstName = "Odin"
});

此外,.Net Framework已经提供了一组非常好的通用集合类,您可以使用这些类,因此您不需要MyGenericList2<T>类。例如,最常用的类是System.Collections.Generic.List

var people = new System.Collections.Generic.List<Person>();

people.Add(new Student
{
    FirstName = "Odin"
});

甚至使用集合初始化语法:

var people = new System.Collections.Generic.List<Person>
{    
    new Student
    {
        FirstName = "Odin"
    }
});

最后,将输出值输出到控制台时遇到的问题是因为C#不知道如何处理类,所以默认输出student.ToString()的值。因为你没有告诉你的班级怎么做,它只输出类型的名称。您可以覆盖ToString,也可以更简单地调用getFirstName()方法:

Console.WriteLine(list[i].getFirstName());