Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用c#泛型重写这两个几乎相同的函数?_C#_Generics - Fatal编程技术网

如何使用c#泛型重写这两个几乎相同的函数?

如何使用c#泛型重写这两个几乎相同的函数?,c#,generics,C#,Generics,我有两个几乎相同的c#函数。因为它们太相似了,我想我应该试试泛型,但我不知道该怎么做。有什么建议吗,还是我找错了方向 public IList<UnitTemplate> UnitTemplates { get; set; } public IList<QualTemplate> QualTemplates { get; set; } public QualTemplate FindQualTemplate(string templateID)

我有两个几乎相同的c#函数。因为它们太相似了,我想我应该试试泛型,但我不知道该怎么做。有什么建议吗,还是我找错了方向

    public IList<UnitTemplate> UnitTemplates { get; set; }
    public IList<QualTemplate> QualTemplates { get; set; }

    public QualTemplate FindQualTemplate(string templateID)
    {
        QualTemplate selectedQualTemplate;
        if (QualTemplates.Count == 0)
            throw new CreatioException("This user's brand has no QualTemplates. There must be at least one available.");
        if (QualTemplates.Count == 1 || String.IsNullOrEmpty(templateID))
            selectedQualTemplate = QualTemplates.First();
        else
            selectedQualTemplate = QualTemplates.Single(x => x.QualTemplateID.ToLower() == templateID.ToLower());
        if (selectedQualTemplate == null)
            throw new CreatioException(String.Format("No QualTemplate with the id {0} could be found for this user's brand.", templateID));
        return selectedQualTemplate;
    }

    public UnitTemplate FindUnitTemplates(string templateID)
    {
        UnitTemplate selectedTemplate;
        if (UnitTemplates.Count == 0)
            throw new CreatioException("This user's brand has no UnitTemplates. There must be at least one available.");
        if (UnitTemplates.Count == 1 || String.IsNullOrEmpty(templateID))
            selectedTemplate = UnitTemplates.First();
        else
            selectedTemplate = UnitTemplates.Single(x => x.UnitTemplateID.ToLower() == templateID.ToLower());
        if (selectedTemplate == null)
            throw new CreatioException(String.Format("No UnitTemplate with the id {0} could be found for this user's brand.", templateID));
        return selectedTemplate;
    }
public IList单元模板{get;set;}
公共IList QualTemplates{get;set;}
公共QualTemplate FindQualTemplate(字符串模板ID)
{
QualTemplate选择QualTemplate;
if(QualTemplates.Count==0)
抛出新的CreationException(“此用户的品牌没有QualTemplates。必须至少有一个可用。”);
if(QualTemplates.Count==1 | | String.IsNullOrEmpty(templateID))
selectedQualTemplate=QualTemplates.First();
其他的
selectedQualTemplate=QualTemplates.Single(x=>x.QualTemplateID.ToLower()==templateID.ToLower());
如果(selectedQualTemplate==null)
抛出新的CreationException(String.Format(“找不到此用户品牌的id为{0}的QualTemplate。”,templateID));
返回selectedQualTemplate;
}
公共单元模板FindUnitTemplates(字符串模板ID)
{
单元模板选择模板;
如果(UnitTemplates.Count==0)
抛出新的CreationException(“此用户的品牌没有UnitTemplates。必须至少有一个可用的。”);
if(UnitTemplates.Count==1 | | String.IsNullOrEmpty(templateID))
selectedTemplate=UnitTemplates.First();
其他的
selectedTemplate=UnitTemplates.Single(x=>x.UnitTemplateID.ToLower()==templateID.ToLower());
如果(selectedTemplate==null)
抛出新的CreationException(String.Format(“找不到此用户品牌的id为{0}的UnitTemplate。”,templateID));
返回所选模板;
}

这不容易做到。UnitTemplates和QualTemplates需要实现相同的接口或具有相同的基类来公开您正在使用的成员,QualTemplate和UnitTemplate也是如此。即使这样,您也需要将要使用的工厂传递给该方法(例如,UnitTemplates作为参数),并且需要在外部指定在单个调用中使用的谓词(因为ID属性名称不同).

您遇到的问题是,这两种方法都使用了两种类型没有共同点的属性:
QualTemplateID
UnitTemplateID
。如果可以对代码结构进行以下更改:

  • 声明
    UnitTemplate
    QualTemplate
    以从公共基类型
    Template

  • 在该基类型中,声明一个属性
    TemplateID

  • 去掉
    QualTemplateID
    UnitTemplateID
    并使用继承的
    TemplateID
    属性

然后,您可以一般地编写该方法:

public TTemplate FindTemplates<TTemplate>(
    IList<TTemplate> templates, string templateID)
    where TTemplate : Template
{
    TTemplate selectedTemplate;
    if (templates.Count == 0)
        throw new CreatioException("This user's brand has no template. There must be at least one available.");
    if (templates.Count == 1 || String.IsNullOrEmpty(templateID))
        selectedTemplate = templates.First();
    else
        selectedTemplate = templates.Single(x => x.TemplateID.ToLower() == templateID.ToLower());
    return selectedTemplate;
}

我会使用一个界面,比如:

public interface ITemplate
{
    string TemplateId { get; }
}
明确实施:

public class UnitTemplate : ITemplate {
    public string UnitTemplateID { get; set; }
    string ITemplate.TemplateId { get { return UnitTemplateID; } }
}
public class QualTemplate : ITemplate
{
    public string QualTemplateID { get; set; }
    string ITemplate.TemplateId { get { return QualTemplateID; } }
}
然后我可以编写一个通用扩展方法来处理任何
T

public static class TemplateExtensions
{
    public static T Find<T>(this ICollection<T> templates, string templateID) where T : ITemplate
    {
        T selectedTemplate;
        if (templates.Count == 0)
            throw new CreatioException("This user's brand has no templates. There must be at least one available.");
        if (templates.Count == 1 || String.IsNullOrEmpty(templateID))
            selectedTemplate = templates.First();
        else
            selectedTemplate = templates.Single(x => x.TemplateId.ToLower() == templateID.ToLower());
        if (selectedTemplate == null)
            throw new CreatioException(String.Format("No template with the id {0} could be found for this user's brand.", templateID));
        return selectedTemplate;
    }
}

如果要避免使用接口,可以使用选择器:

public QualTemplate FindQualTemplate(string templateID)
{
    return Find(QualTemplates, templateID, x => x.QualTemplateID);
}
public UnitTemplate FindUnitTemplates(string templateID)
{
    return Find(UnitTemplates, templateID, x => x.UnitTemplateID);
}
static T Find<T>(ICollection<T> templates, string templateID, Func<T, string> selector)
{
    T selectedTemplate;
    if (templates.Count == 0)
        throw new CreatioException("This user's brand has no templates. There must be at least one available.");
    if (templates.Count == 1 || String.IsNullOrEmpty(templateID))
        selectedTemplate = templates.First();
    else
        selectedTemplate = templates.Single(x => selector(x).ToLower() == templateID.ToLower());
    if (selectedTemplate == null)
        throw new CreatioException(String.Format("No template with the id {0} could be found for this user's brand.", templateID));
    return selectedTemplate;
}
公共QualTemplate FindQualTemplate(字符串模板ID)
{
返回Find(QualTemplates,templateID,x=>x.QualTemplateID);
}
公共单元模板FindUnitTemplates(字符串模板ID)
{
返回Find(UnitTemplates,templateID,x=>x.UnitTemplateID);
}
静态T查找(ICollection模板、字符串模板ID、函数选择器)
{
T选择模板;
如果(templates.Count==0)
抛出新的CreationException(“此用户的品牌没有模板。必须至少有一个可用模板。”);
if(templates.Count==1 | | String.IsNullOrEmpty(templateID))
selectedTemplate=templates.First();
其他的
selectedTemplate=templates.Single(x=>selector(x.ToLower()==templateID.ToLower());
如果(selectedTemplate==null)
抛出新的CreatioException(String.Format(“找不到此用户品牌的id为{0}的模板。”,templateID));
返回所选模板;
}

这将是我所能看到的最简单的解决方案,如果需要,您甚至可以将其作为扩展方法。(如果您不只是移除静电和该部件)

公共静态类扩展{
公共静态T FindTemplates(此IList列表、字符串templateID、Func选择器)
{
T选择模板;
如果(list.Count==0){
抛出新的CreationException(“此用户的品牌没有UnitTemplates。必须至少有一个可用的。”);
}
if(list.Count==1 | | String.IsNullOrEmpty(templateID)){
selectedTemplate=list.First();
}
否则{
selectedTemplate=选择器(templateID);
}
如果(selectedTemplate==null){
抛出新的CreationException(String.Format(“找不到此用户品牌的id为{0}的UnitTemplate。”,templateID));
}
返回所选模板;
}
}

那么用法如下所示:

IList<UnitTemplate> test = new List<UnitTemplate>();
UnitTemplate t = test.FindTemplates("id", (string x) => test.Single(y => y.UnitTemplateID.ToLower() == x.ToLower()));
IList测试=新列表();
UnitTemplate t=test.FindTemplates(“id”,(字符串x)=>test.Single(y=>y.UnitTemplateID.ToLower()==x.ToLower());
您可以使用Func:

public IList<UnitTemplate> UnitTemplates { get; set; }
public IList<QualTemplate> QualTemplates { get; set; }

public QualTemplate FindQualTemplate(string templateID)
{
    return FindTemplatesImpl(templateID, x => x.QualTemplateID, QualTemplates );
}

public UnitTemplate FindUnitTemplates(string templateID)
{
    return FindTemplatesImpl(templateID, x => x.UnitTemplateID, UnitTemplates );
}

public T FindTemplatesImpl<T>(string templateID, Func<T, string> expr, IList<T> templates)
{
    T selectedTemplate;
    if (templates.Count == 0)
        throw new CreatioException("This user's brand has no Templates. There must be at least one available.");

    if (templates.Count == 1 || String.IsNullOrEmpty(templateID))
        selectedTemplate = templates.First();
    else
        selectedTemplate = templates.Single(x => expr(x).ToLower() == templateID.ToLower());

    if (selectedTemplate == null)
        throw new CreatioException(String.Format("No UnitTemplate with the id {0} could be found for this user's brand.", templateID));

    return selectedTemplate;
}
public IList单元模板{get;set;}
公共IList QualTemplates{get;set;}
公共QualTemplate FindQualTemplate(字符串模板ID)
{
返回FindTemplatesImpl(templateID,x=>x.QualTemplateID,QualTemplates);
}
公共单元模板FindUnitTemplates(字符串模板ID)
{
返回FindTemplatesImpl(templateID,x=>x.UnitTemplateID,UnitTemplates);
}
公共T FindTemplatesImpl(字符串模板ID、函数表达式、IList模板)
{
T选择模板;
如果(templates.Count==0)
抛出新的CreationException(“此用户的品牌没有模板。必须至少有一个可用模板。”);
if(templates.Count==1 | | String.IsNullOrEmpty(templateID))
斯雷克
public static class Extension {

     public static T FindTemplates<T>(this IList<T> list, string templateID, Func<string,T> selector) 
       {
        T selectedTemplate;
        if (list.Count == 0){
            throw new CreationException("This user's brand has no UnitTemplates. There must be at least one available.");
        }
        if (list.Count == 1 || String.IsNullOrEmpty(templateID)){
            selectedTemplate =  list.First();
        }
        else{
            selectedTemplate = selector(templateID); 
        }
        if (selectedTemplate == null){
            throw new CreationException(String.Format("No UnitTemplate with the id {0} could be found for this user's brand.", templateID));
        }
        return selectedTemplate;
    }
  }
IList<UnitTemplate> test = new List<UnitTemplate>();
UnitTemplate t = test.FindTemplates("id", (string x) => test.Single(y => y.UnitTemplateID.ToLower() == x.ToLower()));
public IList<UnitTemplate> UnitTemplates { get; set; }
public IList<QualTemplate> QualTemplates { get; set; }

public QualTemplate FindQualTemplate(string templateID)
{
    return FindTemplatesImpl(templateID, x => x.QualTemplateID, QualTemplates );
}

public UnitTemplate FindUnitTemplates(string templateID)
{
    return FindTemplatesImpl(templateID, x => x.UnitTemplateID, UnitTemplates );
}

public T FindTemplatesImpl<T>(string templateID, Func<T, string> expr, IList<T> templates)
{
    T selectedTemplate;
    if (templates.Count == 0)
        throw new CreatioException("This user's brand has no Templates. There must be at least one available.");

    if (templates.Count == 1 || String.IsNullOrEmpty(templateID))
        selectedTemplate = templates.First();
    else
        selectedTemplate = templates.Single(x => expr(x).ToLower() == templateID.ToLower());

    if (selectedTemplate == null)
        throw new CreatioException(String.Format("No UnitTemplate with the id {0} could be found for this user's brand.", templateID));

    return selectedTemplate;
}