C#:传递通用对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9664912/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 08:21:50  来源:igfitidea点击:

C# : Passing a Generic Object

c#genericsmethods

提问by user1229895

I want to have a generic print function...PrintGeneric(T)...in the following case, what am I missing?

我想要一个通用的打印功能...PrintGeneric(T)...在以下情况下,我缺少什么?

As always your help/insight is appreciated...

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

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);
    }
}

采纳答案by jonnystoten

It doesn't compile because T could be anything, and not everything will have the myvarfield.

它不会编译,因为 T 可以是任何东西,并不是所有东西都会有这个myvar字段。

You could make myvara property on ITest:

您可以在以下位置myvar创建属性ITest

public ITest
{
    string myvar{get;}
}

and implement it on the classes as a property:

并将其作为属性在类上实现:

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

and then put a generic constraint on your method:

然后对您的方法施加通用约束:

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

but in that case to be honest you are better off just passing in an ITest:

但在那种情况下,老实说,你最好只传递一个 ITest:

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

回答by Not loved

try

尝试

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

as @Ash Burlaczenko has said you cant name a variable after a keyword, if you reallllly want this prefix with @ symbol to escape the keyword

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

回答by Péter T?r?k

In your generic method, Tis just a placeholder for a type. However, the compiler doesn't per se know anything about the concrete type(s) being used runtime, so it can't assume that they will have a varmember.

在您的泛型方法中,T只是一个类型的占位符。但是,编译器本身并不知道运行时使用的具体类型的任何信息,因此它不能假设它们将具有var成员。

The usual way to circumvent this is to add a generic type constraint to your method declaration to ensure that the types used implement a specific interface (in your case, it could be ITest):

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

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

Then, the members of that interface would be directly available inside the method. However, your ITestis currently empty, you need to declare common stuff there in order to enable its usage within the method.

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

回答by C.Evenhuis

You'll have to provide more information about the generic type T. In your current PrintGenericmethod, Tmight as well be a string, which does not have a varmember.

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

You may want to change varto a property rather than a field

您可能想要更改var为属性而不是字段

public interface ITest
{
    string var { get; }
}

And add a constraint where T: ITestto the PrintGenericmethod.

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

回答by Jon Skeet

You're missing at least a couple of things:

你至少错过了几件事:

  • Unless you're using reflection, the type arguments need to be known at compile-time, so you can't use

    PrintGeneric<test2.GetType()>
    

    ... although in this case you don't need to anyway

  • PrintGenericdoesn't know anything about Tat the moment, so the compiler can't find a member called T

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

    PrintGeneric<test2.GetType()>
    

    ...虽然在这种情况下你不需要

  • PrintGenericT此刻一无所知,因此编译器找不到名为的成员T

Options:

选项:

  • Put a property in the ITestinterface, and change PrintGenericto constrain T:

    public void PrintGeneric<T>(T test) where T : ITest
    {
        Console.WriteLine("Generic : " + test.PropertyFromInterface);
    }
    
  • Put a property in the ITestinterface and remove the generics entirely:

    public void PrintGeneric(ITest test)
    {
        Console.WriteLine("Property : " + test.PropertyFromInterface);
    }
    
  • Use dynamic typing instead of generics if you're using C# 4

  • ITest接口中放置一个属性,并更改PrintGeneric为 constrain 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,请使用动态类型而不是泛型

回答by nolith

You cannot access varwith the generic.

您无法使用var泛型访问。

Try something like

尝试类似的东西

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

And override ToStringmethod [1]

并覆盖ToString方法 [1]

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

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

回答by Moo-Juice

You need to define something in the interface, such as:

你需要在接口中定义一些东西,比如:

public interface ITest
{
    string Name { get; }
}

Implement ITestin your classes:

ITest在您的课程中实施:

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

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

Then restrict your generic Printfunction, to ITest:

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

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