C# 如何通过泛型类型的特定实例重载C方法 来自C++背景,我已经遇到了一个基于泛型类型的特定实例的重载问题。由于只生成了一次Foo类的代码实例,所以在方法内部,这种类型只是Foo,而不是我所希望的Foo或Foo。在C++中,我习惯于将模板实例化为唯一类型。 using System.Collections.Generic; class A { // Concrete class } class B { // Concrete class } class Bar { public void OverloadedMethod(Foo<A> a) {} // do some A related stuff public void OverloadedMethod(Foo<B> b) {} // do some B related stuff public void OverloadedMethod(OtherFoo of) {} // do some other stuff public void VisitFoo(FooBase fb) { fb.Method(this); } } abstract class FooBase { public abstract void Method(Bar b); } class Foo<T> : FooBase { // Class that deals with As and Bs in an identical fashion. public override void Method(Bar b) { // Doesn't compile here b.OverloadedMethod(this); } } class OtherFoo : FooBase { public override void Method(Bar b) { b.OverloadedMethod(this); } } class Program { static void Main(string[] args) { List<FooBase> ListOfFoos = new List<FooBase>(); ListOfFoos.Add(new OtherFoo()); ListOfFoos.Add(new Foo<A>()); ListOfFoos.Add(new Foo<B>()); Bar b = new Bar(); foreach (FooBase fb in ListOfFoos) b.VisitFoo(fb); // Hopefully call each of the Bar::Overloaded methods } }

C# 如何通过泛型类型的特定实例重载C方法 来自C++背景,我已经遇到了一个基于泛型类型的特定实例的重载问题。由于只生成了一次Foo类的代码实例,所以在方法内部,这种类型只是Foo,而不是我所希望的Foo或Foo。在C++中,我习惯于将模板实例化为唯一类型。 using System.Collections.Generic; class A { // Concrete class } class B { // Concrete class } class Bar { public void OverloadedMethod(Foo<A> a) {} // do some A related stuff public void OverloadedMethod(Foo<B> b) {} // do some B related stuff public void OverloadedMethod(OtherFoo of) {} // do some other stuff public void VisitFoo(FooBase fb) { fb.Method(this); } } abstract class FooBase { public abstract void Method(Bar b); } class Foo<T> : FooBase { // Class that deals with As and Bs in an identical fashion. public override void Method(Bar b) { // Doesn't compile here b.OverloadedMethod(this); } } class OtherFoo : FooBase { public override void Method(Bar b) { b.OverloadedMethod(this); } } class Program { static void Main(string[] args) { List<FooBase> ListOfFoos = new List<FooBase>(); ListOfFoos.Add(new OtherFoo()); ListOfFoos.Add(new Foo<A>()); ListOfFoos.Add(new Foo<B>()); Bar b = new Bar(); foreach (FooBase fb in ListOfFoos) b.VisitFoo(fb); // Hopefully call each of the Bar::Overloaded methods } },c#,generics,overloading,C#,Generics,Overloading,有没有办法让这样的东西在C中工作?我不想在Foo中将代码作为单独的类复制到我想要使用它的每一种类型中 编辑: 希望这更清楚一些。编辑:我不确定您是否能够在尝试时完成此操作。我已经尝试了各种各样的技巧,试图让它工作,但无法让它编译。我能做的最好的事情就是将方法调用拉到泛型类之外。如果您的方法调用在外部,那么您可以具体定义泛型中的T。但是,在方法内部,在编译时,编译器不知道t是什么,因此不知道调用哪个重载方法。我能看到的唯一方法是使用开关来确定T的类型,并手动指定要调用的重载 我能做的最好的就是这个

有没有办法让这样的东西在C中工作?我不想在Foo中将代码作为单独的类复制到我想要使用它的每一种类型中

编辑:
希望这更清楚一些。

编辑:我不确定您是否能够在尝试时完成此操作。我已经尝试了各种各样的技巧,试图让它工作,但无法让它编译。我能做的最好的事情就是将方法调用拉到泛型类之外。如果您的方法调用在外部,那么您可以具体定义泛型中的T。但是,在方法内部,在编译时,编译器不知道t是什么,因此不知道调用哪个重载方法。我能看到的唯一方法是使用开关来确定T的类型,并手动指定要调用的重载

我能做的最好的就是这个,这不是你想要的,但它可以被用于类似的效果:

class Stuff<T>
{
    public T value { get; set; }
}

class Program
{
    static void DummyFunc(Stuff<int> inst)
    {
        Console.WriteLine("Stuff<int>: {0}", inst.value.ToString());
    }

    static void DummyFunc(Stuff<string> inst)
    {
        Console.WriteLine("Stuff<string>: {0}", inst.value);
    }
    static void DummyFunc(int value)
    {
        Console.WriteLine("int: {0}", value.ToString());
    }
    static void DummyFunc(string value)
    {
        Console.WriteLine("string: {0}", value);
    }
    static void Main(string[] args)
    {
        var a = new Stuff<string>();
        a.value = "HelloWorld";

        var b = new Stuff<int>();
        b.value = 1;

        var c = "HelloWorld";
        var d = 1;

        DummyFunc(a);
        DummyFunc(b);
        DummyFunc(c);
        DummyFunc(d);
    }
}
并且得到了输出:

Stuff<string>: HelloWorld
Stuff<int>: 1
string: HelloWorld
int: 1
我有四个重载函数,引用了两个引用泛型类,一个用于int,一个用于string,两个引用常规类型,一个用于int,一个用于string,一切正常。。。这就是你想要的吗


编辑:问题似乎不在于重载方法的调用,而是与foreach有关,foreach试图将列表中的所有项转换为与第一个相同的类型,以便引用重载方法。第一项不符合该确切定义的内容将导致编译失败。

编辑:我不确定您是否可以在尝试时完成此操作。我已经尝试了各种各样的技巧,试图让它工作,但无法让它编译。我能做的最好的事情就是将方法调用拉到泛型类之外。如果您的方法调用在外部,那么您可以具体定义泛型中的T。但是,在方法内部,在编译时,编译器不知道t是什么,因此不知道调用哪个重载方法。我能看到的唯一方法是使用开关来确定T的类型,并手动指定要调用的重载

我能做的最好的就是这个,这不是你想要的,但它可以被用于类似的效果:

class Stuff<T>
{
    public T value { get; set; }
}

class Program
{
    static void DummyFunc(Stuff<int> inst)
    {
        Console.WriteLine("Stuff<int>: {0}", inst.value.ToString());
    }

    static void DummyFunc(Stuff<string> inst)
    {
        Console.WriteLine("Stuff<string>: {0}", inst.value);
    }
    static void DummyFunc(int value)
    {
        Console.WriteLine("int: {0}", value.ToString());
    }
    static void DummyFunc(string value)
    {
        Console.WriteLine("string: {0}", value);
    }
    static void Main(string[] args)
    {
        var a = new Stuff<string>();
        a.value = "HelloWorld";

        var b = new Stuff<int>();
        b.value = 1;

        var c = "HelloWorld";
        var d = 1;

        DummyFunc(a);
        DummyFunc(b);
        DummyFunc(c);
        DummyFunc(d);
    }
}
并且得到了输出:

Stuff<string>: HelloWorld
Stuff<int>: 1
string: HelloWorld
int: 1
我有四个重载函数,引用了两个引用泛型类,一个用于int,一个用于string,两个引用常规类型,一个用于int,一个用于string,一切正常。。。这就是你想要的吗


编辑:问题似乎不在于重载方法的调用,而是与foreach有关,foreach试图将列表中的所有项转换为与第一个相同的类型,以便引用重载方法。第一项不符合精确定义的内容将导致编译失败。

我现在有一段真正完整的代码来演示这个问题。OP注意:请在发布代码之前尝试编译代码。为了走到这一步,我必须做很多事情。让别人尽可能容易地帮助你是件好事。我还删除了一些无关的部分。OtherFoo在这里并不重要,FooBase也不重要

class A {}
class B {}

class Bar
{
    public static void OverloadedMethod(Foo<A> a) { }
    public static void OverloadedMethod(Foo<B> b) { }
}

class Foo<T>
{
    // Class that deals with As and Bs in an identical fashion.
    public void Method()
    {
        // Doesn't compile here
        Bar.OverloadedMethod(this);
    }
}
是的,这不可编译。你到底期望它做什么?请记住,重载解析是在编译时执行的,而不是在执行时。正如fallen888所说,您可以强制转换并调用适当的重载方法,但是您希望编译器选择两个重载中的哪一个?你想用Foo而不是Foo或Foo做什么


这都证明了.NET泛型确实与C++模板有很大的不同,当然……/P>< P>我现在有一个真正完整的代码来演示这个问题。OP注意:请在发布代码之前尝试编译代码。为了走到这一步,我必须做很多事情。让别人尽可能容易地帮助你是件好事。我还删除了一些无关的部分。OtherFoo在这里并不重要,FooBase也不重要

class A {}
class B {}

class Bar
{
    public static void OverloadedMethod(Foo<A> a) { }
    public static void OverloadedMethod(Foo<B> b) { }
}

class Foo<T>
{
    // Class that deals with As and Bs in an identical fashion.
    public void Method()
    {
        // Doesn't compile here
        Bar.OverloadedMethod(this);
    }
}
是的,这不可编译。你到底期望它做什么?请记住,重载解析是在编译时执行的,而不是在执行时。正如fallen888所说,您可以强制转换并调用适当的重载方法,但是您希望编译器选择两个重载中的哪一个?你想用Foo而不是Foo或Foo做什么

这一切都证明了.NET泛型确实与C有着显著的不同
++模板,当然……

我没有试过,但似乎你应该能够通过使A&B可访问(例如使用非循环访问者模式)来实现你想要的。

我没有试过,但似乎你应该能够通过使A&B可访问(例如使用非循环访问者模式)来实现你想要的。

我希望找到一种更简单的方法要做到这一点,但现在我要说:

将Foo类替换为以下类:

abstract class Foo<T> : FooBase
{
    // Class that deals with As and Bs in an identical fashion.
}

class Foo_A : Foo<A>
{
    public override void Method(Bar b)
    {
        b.OverloadedMethod(this);
    }
}

class Foo_B : Foo<B>
{
    public override void Method(Bar b)
    {
        // Doesn't compile here
        b.OverloadedMethod(this);
    }
}
并将实例化更改为

List<FooBase> ListOfFoos = new List<FooBase>();
ListOfFoos.Add(new OtherFoo());
ListOfFoos.Add(new Foo_A());
ListOfFoos.Add(new Foo_B());

这至少不需要在Foo中重复代码,只需要我转发构造函数。

我希望找到一种更简单的方法来实现这一点,但现在我要做的是:

将Foo类替换为以下类:

abstract class Foo<T> : FooBase
{
    // Class that deals with As and Bs in an identical fashion.
}

class Foo_A : Foo<A>
{
    public override void Method(Bar b)
    {
        b.OverloadedMethod(this);
    }
}

class Foo_B : Foo<B>
{
    public override void Method(Bar b)
    {
        // Doesn't compile here
        b.OverloadedMethod(this);
    }
}
并将实例化更改为

List<FooBase> ListOfFoos = new List<FooBase>();
ListOfFoos.Add(new OtherFoo());
ListOfFoos.Add(new Foo_A());
ListOfFoos.Add(new Foo_B());

这至少不需要在Foo中复制代码,只需要我转发构造函数。

这适用于静态情况。处理实例函数会有点复杂。这可能为处理实例方法提供了一种合理的方法

class Program
{
    static void Main(string[] args)
    {
        var testA = new Foo<A>();
        testA.Method();
        var testB = new Foo<B>();
        testB.Method();
        Console.ReadLine();
        var testString = new Foo<string>(); //Fails
        testString.Method(); 
        Console.ReadLine();
    }
}

class A { }
class B { }
class Bar
{
    public static void OverloadedMethod(Foo<A> a)
    {
        Console.WriteLine("A");
    }
    public static void OverloadedMethod(Foo<B> b)
    {
        Console.WriteLine("B");
    }
}
class Foo<T>
{
    static Foo()
    {
        overloaded = (Action<Foo<T>>)Delegate.CreateDelegate(typeof(Action<Foo<T>>), typeof(Bar).GetMethod("OverloadedMethod", new Type[] { typeof(Foo<T>) }));
    }

    public void Method()
    {
        overloaded(this);
    }

    private static readonly Action<Foo<T>> overloaded;
}

这适用于静态情况。处理实例函数会有点复杂。这可能为处理实例方法提供了一种合理的方法

class Program
{
    static void Main(string[] args)
    {
        var testA = new Foo<A>();
        testA.Method();
        var testB = new Foo<B>();
        testB.Method();
        Console.ReadLine();
        var testString = new Foo<string>(); //Fails
        testString.Method(); 
        Console.ReadLine();
    }
}

class A { }
class B { }
class Bar
{
    public static void OverloadedMethod(Foo<A> a)
    {
        Console.WriteLine("A");
    }
    public static void OverloadedMethod(Foo<B> b)
    {
        Console.WriteLine("B");
    }
}
class Foo<T>
{
    static Foo()
    {
        overloaded = (Action<Foo<T>>)Delegate.CreateDelegate(typeof(Action<Foo<T>>), typeof(Bar).GetMethod("OverloadedMethod", new Type[] { typeof(Foo<T>) }));
    }

    public void Method()
    {
        overloaded(this);
    }

    private static readonly Action<Foo<T>> overloaded;
}

你能澄清一下吗?您是否需要它来接受具有特定类型的泛型类的实例?i、 MyGenericClass?您希望调用哪个重载?您的示例不清楚,因为像foo这样的东西-A和B是实际类型吗?使示例完整,即我们可以编译并得到您感兴趣的错误,这会有很大帮助。您能澄清一下吗?您是否需要它来接受具有特定类型的泛型类的实例?i、 MyGenericClass?您希望调用哪个重载?您的示例不清楚,因为像foo这样的东西-A和B是实际类型吗?使示例完整,即我们可以编译并获得您感兴趣的错误,这会有很大帮助。这只是重载-而不是泛型中的重载。哦,我现在明白了,我想我们是在尝试使用泛型重载,而不是泛型本身中的重载。。。似乎我完全没有抓住要点:P这只是重载——不是泛型中的重载。哦,我现在明白了,我想我们是在尝试使用泛型重载,而不是泛型本身中的重载。。。我似乎完全没有抓住要点:p额外的类与编译器错误无关——它们与我希望传达的设计有关。我原本希望它能起作用,但编译错误让我对泛型如何工作做了更多的研究。我希望能找到某种解决方法,以获得这种类型为Foo的上下文,而不仅仅是肯定我确实有编译错误。但根本原因是理解为什么会有编译器错误。一旦你理解了,在泛型和C++模板之间的差异,IMO,你可能很想改变你的设计。额外的类不是编译器错误——它们是我希望传达的设计。我原本希望它能起作用,但编译错误让我对泛型如何工作做了更多的研究。我希望能找到某种解决方法,以获得这种类型为Foo的上下文,而不仅仅是肯定我确实有编译错误。但根本原因是理解为什么会有编译器错误。一旦你了解了在泛型和C++模板之间的差异,IMO,你可能很想改变你的设计。