如何将泛型列表设置为相同类型的预先存在列表

本文关键字:列表 同类型 存在 泛型 设置 | 更新日期: 2023-09-27 17:52:56

我使用c#并有4个现有列表,每个列表都是不同的类型(即List<Doctor>, List<Patient>等)

我有一个通用的搜索方法,它接收类型T,应该使用LINQ搜索基于类型T的适当列表。

我创建了一个var List<T> listToSearch,并希望使用if将其设置为适当的列表,但我不能将listToSearch设置为其中的任何一个。

代码:

// at class level:
    private List<Doctor> doctorList;
    private List<Patient> patientList;
    private List<Visit> visitList;
    private List<Treatment> treatmentList;
    public IEnumerable search<T>(string field, string rangeStart, string rangeEnd = null)
    {
        List<T> listToSearch = null;
        if (typeof(T) == typeof(Doctor)) { listToSearch = doctorList; }
        if (typeof(T) == typeof(Patient)) { listToSearch = patientList; }
        if (typeof(T) == typeof(Visit)) { listToSearch = visitList; }
        if (typeof(T) == typeof(Treatment)) { listToSearch = treatmentList; }

        // more code that isn't relevant to the question here
    }

每个typeof(T)行显示一个错误:

"不能隐式地将类型'System.Collections.Generic.List<Doctor/Patient/Visit/Treatment>'转换为'System.Collections.Generic.List<T>'

如何修改这段代码以允许使用泛型列表?

如何将泛型列表设置为相同类型的预先存在列表

不起作用的原因是 T在编译时是未知的。您要求使用已知类型的列表并将其用作未知类型的列表,这是不允许的(没有动态或其他非编译时类型安全机制)。

因为你只支持4种类型,听起来你需要4个search方法来调用一个通用的公共方法(如果合适的话):

public IEnumerable<Doctor> searchDoctors(string field, string rangeStart, string rangeEnd = null)
{
    List<Doctor> listToSearch = doctorList;
    // more code that isn't relevant to the question here
}
public IEnumerable<Patient> searchPatients(string field, string rangeStart, string rangeEnd = null)
{
    List<Patient> listToSearch = patientList;
    // more code that isn't relevant to the question here
}
public IEnumerable<Visit> searchVisits(string field, string rangeStart, string rangeEnd = null)
{
    List<Visit> listToSearch = visitList;
    // more code that isn't relevant to the question here
}
public IEnumerable<Treatment> searchTreatments(string field, string rangeStart, string rangeEnd = null)
{
    List<Treatment> listToSearch = treatmentList;
    // more code that isn't relevant to the question here
}

否则,你将有大量的代码来验证/转换类型,这很容易受到运行时错误的影响。

注:

因为你是c#新手-我建议不要尝试使用泛型等进行过多的优化/重构。编写工作的代码(即使它使用复制粘贴,而不是DRY等),然后使更好。否则,您将花费大量时间试图将程序硬塞进某种模式,而不是考虑程序应该如何工作。

您可以先将其强制转换为一个List<T>对象:

if (typeof(T) == typeof(Doctor)) { listToSearch = (List<T>)(object)doctorList; }

你要求的事情是不可能的。

我建议将您的listToSearch输入为IList。这将保持尽可能多的通用性。您可以访问所有常见的列表操作,而不必依赖泛型。

IList listToSearch = null;

在了解泛型的用途之前,我遇到了类似的情况。在我的情况下,我试图减少将数据添加到处理程序所需的方法数量,然后将其写入xml文件,这与您想要完成的目标并不太远。我试图将暴露的方法数量从8个减少到1个。我最终使用了一个接口,而不是一个泛型。

简而言之,您可能可以通过使用interface而不是generic来获得所需的功能。斯坦利是对的。编写有效的代码,然后改进。这样,您就可以尝试消除更改以恢复功能的选项。此外,Eric Lippert写了关于泛型的主题(这个帖子是stack overflow,我现在找不到它),如果你写了一个使用泛型的方法,并立即抛出逻辑语句来分类对象类型是什么,那么你使用泛型是错误的。

如果你是,至少,返回IEnumerable<T>我可以理解使用类型参数,但你在这里做的是重新发明方法重载。

试试这个:

public IEnumerable<Doctor> SearchDoctors(string field, string rangeStart, string rangeEnd = null)
{
    return Search(doctorList, field, rangeStart, rangeEnd);
}
public IEnumerable<Patient> SearchPatients(string field, string rangeStart, string rangeEnd = null)
{
    return Search(patientList, field, rangeStart, rangeEnd);
}
public IEnumerable<Visit> SearchVisits(string field, string rangeStart, string rangeEnd = null)
{
    return Search(visitList, field, rangeStart, rangeEnd);
}
public IEnumerable<Treatment> SearchTreatments(string field, string rangeStart, string rangeEnd = null)
{
    return Search(treatmentList, field, rangeStart, rangeEnd);
}
private IEnumerable<T> Search<T>(IEnumerable<T> list, string field, string rangeStart, string rangeEnd)
{
    // more code that isn't relevant to the question here
}
顺便说一下,您是否知道编译后调用者中的默认参数值是硬编码的?

考虑改成:

public IEnumerable<Doctor> SearchDoctors(string field, string rangeStart)
{
    return Search(doctorList, field, rangeStart);
}

public IEnumerable<Doctor> SearchDoctors(string field, string rangeStart, string rangeEnd)
{
    return Search(doctorList, field, rangeStart, rangeEnd);
}
public IEnumerable<Patient> SearchPatients(string field, string rangeStart)
{
    return Search(patientList, field, rangeStart);
}
public IEnumerable<Patient> SearchPatients(string field, string rangeStart, string rangeEnd)
{
    return Search(patientList, field, rangeStart, rangeEnd);
}
public IEnumerable<Visit> SearchVisits(string field, string rangeStart)
{
    return Search(visitList, field, rangeStart);
}
public IEnumerable<Visit> SearchVisits(string field, string rangeStart, string rangeEnd)
{
    return Search(visitList, field, rangeStart, rangeEnd);
}
public IEnumerable<Treatment> SearchTreatments(string field, string rangeStart)
{
    return Search(treatmentList, field, rangeStart);
}
public IEnumerable<Treatment> SearchTreatments(string field, string rangeStart, string rangeEnd)
{
    return Search(treatmentList, field, rangeStart, rangeEnd);
}
private IEnumerable<T> Search<T>(IEnumerable<T> list, string field, string rangeStart, string rangeEnd = null)
{
    // more code that isn't relevant to the question here
}