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中工作?我不想在Foo中将代码作为单独的类复制到我想要使用它的每一种类型中 编辑: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的类型,并手动指定要调用的重载 我能做的最好的就是这个
希望这更清楚一些。编辑:我不确定您是否能够在尝试时完成此操作。我已经尝试了各种各样的技巧,试图让它工作,但无法让它编译。我能做的最好的事情就是将方法调用拉到泛型类之外。如果您的方法调用在外部,那么您可以具体定义泛型中的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,你可能很想改变你的设计。