【问题标题】:C# How do i access an element of a class when the type of class is Generic? [duplicate]C#当类的类型是Generic时如何访问类的元素? [复制]
【发布时间】:2011-04-18 13:27:28
【问题描述】:

可能重复:
C# how do I compare two objects if they are of same type?

我有一个通用函数,

class Something {
    public int found;
    public Something() {
        this.found = true;
    }
}
List<Something> something;

public int countFound<T>(List<T> Organisms)
{
    if (typeof(T) == typeof(Something))
    {
        foreach (T organism in Organisms)
        {
            // here i want to check something like organism.found == true how do i do it?
        }
    }
    return 0;
}

提前感谢所有帮助!

【问题讨论】:

  • 我认为标题具有误导性,问题是如何处理泛型类型方法来访问某些属性。
  • 让我说,如果你在泛型类型参数上进行分支,你所做的可能不是很通用。

标签: c# generics types comparison compare


【解决方案1】:

你可能想要这样的东西:

class Organism
{
    public bool Found
    {
        get;
        set;
    }
}

class Something : Organism
{
    public Something()
    {
        this.Found = true;
    }
}

public class Program
{
    public int countFound<T>(List<T> Organisms)
        where T : Organism
    {
        foreach (T organism in Organisms)
        {
            if (organism.Found)
            {
                // Do something with the organism
            }
        }

        return 0;
    }
}

这里的重点是:

  • 您有一个名为 Organism 的通用基类,它定义了 Found 属性
  • Something 类派生自 Organism,在构造时将 Found 设置为 true
  • CountFound 方法在 T 上有一个通用约束(where 子句),指定它必须从 Organism 派生(The Something 符合此标准)。然后,这允许您使用 Organism 在方法中提供的任何方法或属性 - 在本例中为 Organism.Found。

【讨论】:

  • 或者,就像 ZoolWay 建议的那样,您可以在所有类上创建一个接口。但是,鉴于所有 Organism 派生类都可能提供 Found 属性,那么使用这样的基类可能最有意义。
【解决方案2】:

这里有两个选项,具体取决于您希望函数执行的操作:

如果countFound 函数必须采用T 的所有类型,但是当T 是(或继承自)Something 时你想要一个特殊情况,那么你可以使用这个:

public int countFound<T>(List<T> Organisms)
{
    if (typeof(T) == typeof(Something) || typeof(T).IsSubclassOf(typeof(Something)))
    {
        foreach (T organism in Organisms)
        {
            Something s = (Something)(object)organism;

            // do whatever you like with s
        }
    }
    return 0;
}

如果您希望函数在T 是(或继承自)Something 时采用T 类型,那就更简单了:

public int countFound<T>(List<T> Organisms) where T : Something
{
    foreach (T organism in Organisms)
    {
        // here organism will have all of the properties of Something
    }

    return 0;
}

【讨论】:

    【解决方案3】:

    您必须将泛型限制为一个(或多个)接口,该接口要求实现泛型所需的属性!

    假设接口 IFound 实现了您要检查的属性:

    public int countFound<T>(List<T> Organisms) where T : IFound
    {     
        if (typeof(T) == typeof(Something))     
        {         
             foreach (T organism in Organisms)         
             {
                  if(organism.found)) // done because IFound tells T has a property with this name
             }
        }     
        return 0; 
    } 
    

    IFound 是一个你必须自己实现的接口。例如:

    interface IFound
    {
        bool Found { get; }
    }
    

    你的类Something必须实现IFound:

    class Something : IFound
    {
        public bool Found
        {
            get { return true; } // implement your condition in a method called here
        }
    }
    

    然后你可以随意调用你的方法:

    int a = countFound<Something>(List<Something> parameter);
    

    【讨论】:

    • 对我不起作用 什么是 IFound?
    • 查看我的编辑。您可以选择任何您认为有意义的名称。此外,您想与 countFound() 方法一起使用的每个类都必须实现这一点 - 意味着您的! - 接口。
    • 接口上不能有字段。但更重要的是@softplaza 应该使它成为一个属性。不要公开公共字段。
    • 现在如何使用 countFound 函数?就像我怎么称呼它? countFound(Something) 对我不起作用
    • @Martinho Fernandes:是的,我的意思是一个界面,但没有正确记住语法;)@softplaza 我进一步更新了示例。请阅读界面主题。
    【解决方案4】:

    在您的场景中,您似乎不想尝试实现相等函数,因为相等总是在您正在比较的类型的上下文中定义(每种类型的特定代码进行比较)。如果您的所有 T 都是通用类型(基类)并且相等条件可以用基类的通用属性等表示,那么这对您有用...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-17
      • 1970-01-01
      • 2013-07-13
      • 1970-01-01
      • 2020-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多