C#专门化泛型类

7

是否可以在C#中进行以下专业化? 我可以在C ++中做到这一点,但不知道如何在C#中实现相同的结果。

class GenericPrinter<T>
{
    public void Print()
    {
        Console.WriteLine("Unspecialized method");
    }
}

class GenericPrinter<int>
{
    public void Print()
    {
         Console.WriteLine("Specialized with int");
    }
}

新增:

使用建议的GenericPrinterInt解决方案的问题是我需要显式地创建它。new GenericPrinter<int>仍将打印出Unspecialized method

我想要的是在另一个泛型类中使用这个GenericPrinter而不知道T是否等于int或其他内容。


5
C++模板不是.NET泛型。你不能这样做。 - Lyubomyr Shaydariv
2
这里有一篇非常好的阅读材料,甚至解释了Java泛型的区别:https://dev59.com/C3VD5IYBdhLWcg3wRpiX。 - Lyubomyr Shaydariv
1
你不能这样做。你需要找到其他方法来处理这种情况。 - Ben Aaronson
你可以将你的打印函数写成通用的 'public void Print<T>()'。 - Benj
@Nosturion,请查看我的更新答案 - Dmitry
3个回答

10

我想在C#中最接近的可能是:

class GenericPrinter<T>
{
    public virtual void Print()
    {
        Console.WriteLine("Unspecialized method");
    }
}

class IntPrinter : GenericPrinter<int>
{
    public override void Print()
    {
         Console.WriteLine("Specialized with int");
    }
}

否则,答案是你不能专门从事C#。
正如Lyubomyr Shaydariv在他的评论中所说:
“C++模板不是.NET泛型。 你做不到。”
从您的编辑中,我猜您将进行某种类型检查。
例如,您可以使用字典来完成此操作。
class GenericPrinter<T>
{
    private Dictionary<Type, Action> _actions
        = new Dictionary<Type, Action>()
    {
        { typeof(int), PrintInt }
    };

    public virtual void Print()
    {
        foreach (var pair in _actions)
            if (pair.First == typeof(T))
            {
                pair.Second();
                return ;
            }
        Console.WriteLine("Unspecialized method");
    }

    public virtual void PrintInt()
    {
        Console.WriteLine("Specialized with int");
    }
}

如您所见,您需要为每种类型创建一个方法来处理它们。当您尝试将T作为int进行操作时,您可能会遇到一些问题。由于T是真正的泛型(它没有任何限制),因此它更有可能在您的代码中作为对象(而不是在运行时),您需要像这样进行强制转换:(int)(object)yourTVariable在您确定T是int的方法中。
但对于这部分内容,我想我的同行们会比我给您提供更好的答案。
如果只是为了显示您正在使用的类型:
public virtual void Print()
{
    Console.WriteLine($"Specialized with {typeof(T).Name}");
}

但是你将不再拥有未特化的信息(如果你仔细想一想,你不能实例化一个没有指定类型的GenericPrinter。那么有一个显示“未特化”的方法就没有意义了,你总是会有一个指定的类型)。

无论如何,答案仍然是相同的,你不能在C#中专门化一个泛型


2
速度很快,点个赞。你比我快了1分钟。;) - Dmitry
1
@Dmitry:(即使规则禁止这种评论)谢谢:) - romain-aga

6
在C#中不可能做到这一点。相反,您可以使用继承:
class GenericPrinter<T>
{
    public virtual void Print()
    {
        Console.WriteLine("Unspecialized method");
    }
}

class GenericPrinterInt : GenericPrinter<int>
{
    public override void Print()
    {
        Console.WriteLine("Specialized with int");
    }
}

根据更新的问题,我只能建议您采用以下方法。您可以创建一个静态工厂方法,在该方法中检查 T 的类型,并在类型匹配条件时实例化适当的专用类:

class GenericPrinter<T>
{
    public static GenericPrinter<T> Create()
    {
        if (typeof(int).IsAssignableFrom(typeof(T)))
            return (GenericPrinter<T>)(object)new GenericPrinterInt();

        if (typeof(double).IsAssignableFrom(typeof(T)))
            return (GenericPrinter<T>)(object)new GenericPrinterDouble();

        // Other types to check ...

        return new GenericPrinter<T>();
    }

    public virtual void Print()
    {
        Console.WriteLine("Unspecialized method");
    }
}

class GenericPrinterInt : GenericPrinter<int>
{
    public override void Print()
    {
        Console.WriteLine("Specialized with int");
    }
}

class GenericPrinterDouble : GenericPrinter<double>
{
    public override void Print()
    {
        Console.WriteLine("Specialized with double");
    }
}

另一个通用类:

class SomeGenericClass<T>
{
    public readonly GenericPrinter<T> Printer = GenericPrinter<T>.Create();
}

使用样例:

var intClass = new SomeGenericClass<int>();
intClass.Printer.Print();
// Output: Specialized with int

var doubleClass = new SomeGenericClass<double>();
doubleClass.Printer.Print();
// Output: Specialized with double

var stringClass = new SomeGenericClass<string>();
stringClass.Printer.Print();
// Output: Unspecialized method

2
我们之间只有一分钟的时间差,我们得到了完全相同的答案 x) - romain-aga
1
既然楼主编辑了他的帖子,你可以做出与我不同的东西,无论速度如何。 ;) - romain-aga

0

你可以这样做,但是你需要将你的代码移入 lambda 表达式或者某种类型的 lambda。 虽然不太美观,但是它很快(没有查找)并且具有专门化功能。 你可以根据自己的需求进行调整。

微软啊,我们不应该这么做。 . NET 有多少改进却没有专门化。

public class GenericPrinter<T>
{
    public static GenericPrint()
    {
       T thing = default(T)
       switch(thing)
       {
       case int ival:
          _Print = ()=>
              {
                  Console.WriteLine("Specialized Int print Code");
              };
            break;
        default:
          _Print = ()=>
            {
              Console.WriteLine("Some generic print code");
            };
            break;

       }
   }

   // will be unique for every type of T
   public static Action _Print=null;
 
   public void Print()
   { 
       _Print();
   }

}

用法是相同的

var printer = new GenericPrinter<int>();
printer.Print();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接