【问题标题】:Passing a generic class into function at compile time在编译时将泛型类传递给函数
【发布时间】:2013-04-24 02:17:12
【问题描述】:

下面的代码可以在 c# 中工作吗?

public class Foo
{
    public string Name { get; set; }
}

public class Related_Foo
{
    public string Name { get; set; }
}

class Program
{
    static void do_something<T>(T t)
    {
        string n = t.Name;
    }

    static void Main(string[] args)
    {
        Foo f = new Foo();

        do_something(f);
    }
}

在 .Net 4 中,编译器抱怨:

“T”不包含“名称”的定义,并且找不到接受“T”类型的第一个参数的扩展方法“名称”(您是否缺少 using 指令或程序集引用?)

【问题讨论】:

  • 好吧,既然您尝试了它并清楚地得到了编译器错误,答案是“否”。因此,您已经回答了自己的问题,以下代码将不起作用。也许你应该解释你想做什么并询问如何实现这个目标,而不是问一个你已经回答过的问题。

标签: c# generics


【解决方案1】:

您需要对泛型类型 T 施加约束 - 否则编译器应该如何知道它?

创建一个Ifoo,然后

do_something<T>(T t) where T : IFoo  

interface IFoo
{
    string Name {get;set;}
}

【讨论】:

    【解决方案2】:

    不,此代码在 C# 中不起作用,因为没有任何东西可以限制类型 T 具有名为 Name 的属性。 C# 中的模板与 C++ 中的模板不同,编译器可以在编译时扩展它们并验证使用的某些成员是否确实存在。

    要使其工作,您可以添加一个约束,即T 必须是具有名为 name 的属性的类型。比如创建一个接口:

    public interface IFoo
    {
        string Name { get; }
    }
    

    让你的类实现这个接口。

    然后将约束添加到您的方法中,如下所示:

    static void do_something<T>(T t) where T : IFoo
    {
        string n = t.Name;
    }
    

    如果您的所有类都有一个公共基类,该基类具有属性Name,例如如果Related_Foo 派生自Foo,您可以将其限制为类类型,语法相同:

    static void do_something<T>(T t) where T : Foo
    {
        string n = t.Name;
    }
    

    【讨论】:

      【解决方案3】:

      如果 do_something 应始终采用 Foo 或从 Foo 派生的任何内容(而不是始终具有名为 Name 的属性),您可以这样做:

       static void do_something<T>(T t) where T : Foo
       {
            string n = t.Name;
       }
      

      这将传入的 Type 限制为 Foo 类型或从它派生的任何类型。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-19
        相关资源
        最近更新 更多