C#:传递通用对象

时间:2012-03-12 09:56:26

标签: c# generics methods

我想要一个通用的打印功能... PrintGeneric(T)......在下面的例子中,我缺少什么?

一如既往,感谢您的帮助/见解......

public interface ITest
{}

public class MyClass1 : ITest
{
    public string myvar = "hello 1";
}

public class MyClass2 : ITest
{
    public string myvar = "hello 2";
}

class DoSomethingClass
{

    static void Main()
    {
        MyClass1 test1 = new MyClass1();
        MyClass2 test2 = new MyClass2();

        Console.WriteLine(test1.myvar);
        Console.WriteLine(test2.myvar);             
        Console.WriteLine(test1.GetType());

        PrintGeneric(test1);
        PrintGeneric<test2.GetType()>(test2);
    }

    // following doesn't compile
    public void PrintGeneric<T>(T test)
    {
        Console.WriteLine("Generic : " + test.myvar);
    }
}

7 个答案:

答案 0 :(得分:24)

它没有编译,因为T可以是任何东西,而不是所有东西都有myvar字段。

您可以myvar上的ITest属性:

public ITest
{
    string myvar{get;}
}

并在类上实现它作为属性:

public class MyClass1 : ITest
{
    public string myvar{ get { return "hello 1"; } }
}

然后对您的方法设置一个通用约束:

public void PrintGeneric<T>(T test) where T : ITest
{
    Console.WriteLine("Generic : " + test.myvar);
}

但在这种情况下,说实话,你最好只是传递一个ITest:

public void PrintGeneric(ITest test)
{
    Console.WriteLine("Generic : " + test.myvar);
}

答案 1 :(得分:6)

你至少缺少一些东西:

  • 除非您使用反射,否则需要在编译时知道类型参数,因此您无法使用

    PrintGeneric<test2.GetType()>
    

    ......虽然在这种情况下你无论如何都不需要

  • PrintGeneric目前对T一无所知,因此编译器无法找到名为T的成员

选项:

  • ITest界面中添加一个媒体资源,然后将PrintGeneric更改为约束T

    public void PrintGeneric<T>(T test) where T : ITest
    {
        Console.WriteLine("Generic : " + test.PropertyFromInterface);
    }
    
  • ITest界面中放置一个属性并完全删除泛型:

    public void PrintGeneric(ITest test)
    {
        Console.WriteLine("Property : " + test.PropertyFromInterface);
    }
    
  • 如果您使用的是C#4,请使用动态类型代替泛型

答案 2 :(得分:2)

在通用方法中,T只是一个类型的占位符。但是,编译器本身并不了解运行时使用的具体类型,因此不能假定它们将具有var成员。

规避这种情况的常用方法是在方法声明中添加泛型类型约束,以确保使用的类型实现特定的接口(在您的情况下,它可以是ITest):

public void PrintGeneric<T>(T test) where T : ITest

然后,该接口的成员将直接在该方法中可用。但是,您的ITest目前为空,您需要在那里声明常用内容,以便在方法中使用它。

答案 3 :(得分:2)

您必须提供有关通用类型T的更多信息。在您当前的PrintGeneric方法中,T也可能是string,其中没有var成员。

您可能希望将var更改为属性而非字段

public interface ITest
{
    string var { get; }
}

并向where T: ITest方法添加约束PrintGeneric

答案 4 :(得分:1)

您需要在界面中定义一些内容,例如:

public interface ITest
{
    string Name { get; }
}

在您的课程中实施ITest

public class MyClass1 : ITest
{
    public string Name { get { return "Test1"; } }
}

public class MyClass2 : ITest
{
    public string Name { get { return "Test2"; } }
}

然后将您的通用Print功能限制为ITest

public void Print<T>(T test) where T : ITest
{
}

答案 5 :(得分:0)

public void PrintGeneric<T>(T test) where T: ITest
{
    Console.WriteLine("Generic : " + test.@var);
}

正如@Ash Burlaczenko所说,你不能在一个关键字之后命名一个变量,如果你真的希望这个带有@符号的前缀来转义关键字

答案 6 :(得分:0)

您无法使用通用。{/ p>访问var

尝试类似

的内容
Console.WriteLine("Generic : {0}", test);

并覆盖ToString方法[1]

[1] http://msdn.microsoft.com/en-us/library/system.object.tostring.aspx