【发布时间】:2009-09-09 14:02:00
【问题描述】:
我可能遗漏了一些非常基本的东西,但我无法弄清楚为什么我在某些代码中出现编译错误,而且我没有在几乎相同的代码中得到它。
所以我确实在这里遇到了错误:
//parent.GetChildren() returns a IEnumerable<IBase>
F1<T>(T parent, Func<string, T, string> func) where T: IBase
{
F1(parent.GetChildren(), func);
//This would wok instead:
//F1(parent.GetChildren().Select(c=> (T)c), func);
}
F1<T>(IEnumerable<T> children, Func<string, T, string> func) where T: IBase
{
...
}
但我不在这里:
//parent.GetChildren() returns a IEnumerable<IBase>
F1<T>(T parent, Func<string, string, string> func) where T: IBase
{
//Works, no casting required
F1(parent.GetChildren(), func);
}
F1<T>(IEnumerable<T> children, Func<string, string, string> func) where T: IBase
{
...
}
基本上,如果我在传递的参数函数中使用泛型类型 T 作为其参数之一,我会得到以下编译错误:
错误 1:“ConsoleApplication1.Program.FooConsumer.Consume1<ConsoleApplication1.Program.IBase>(System.Collections.Generic.IEnumerable<ConsoleApplication1.Program.IBase>, string, System.Func<string,ConsoleApplication1.Program.IBase,string>)”的最佳重载方法匹配有一些无效参数
错误 2:参数“3”:无法从“System.Func<string,T,string>”转换为“System.Func<string,ConsoleApplication1.Program.IBase,string>”
这里是完整的示例代码,请参考注释代码(取消注释会得到编译错误):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
interface IBase
{
string GetName();
IEnumerable<IBase> GetChildren();
}
class Foo : IBase
{
private string _Name;
public Foo(string name)
{
_Name = name;
}
public string GetName()
{
return _Name;
}
public IEnumerable<IBase> GetChildren()
{
var r = new List<IBase>();
r.Add(new Foo("foo 1"));
r.Add(new Foo("foo 2"));
return r;
}
}
class FooConsumer
{
public string Consume1<T>(IEnumerable<T> objects, string template, Func<string, T, string> func) where T : IBase
{
var s = "";
foreach (var o in objects)
{
s += func(template, o);
}
return s;
}
public string Consume2<T>(IEnumerable<T> objects, string template, Func<string, string, string> func) where T : IBase
{
var s = "";
foreach (var o in objects)
{
s += func(template, o.GetName()) + "\n";
}
return s;
}
//Here if I don't cast each child as a T I get an error
public string Consume1<T>(T parent_object, string template, Func<string, T, string> func) where T : IBase
{
// return this.Consume1(parent_object.GetChildren(), template, func); //<-- UNCOMMENTING THIS WOULD NOT COMPILE
return this.Consume1(parent_object.GetChildren().Select(c => (T)c), template, func);
}
//Here I would expect it to behave identically, but instead I don't get an Error and code compiles fine.
//How can the last parameter be affecting the first parameter?!
public string Consume2<T>(T parent_object, string template, Func<string, string, string> func) where T : IBase
{
return this.Consume2(parent_object.GetChildren(), template, func); //<-- THIS CALL DOES NOT DO THE CAST BUT COMPILES JUST FINE!!!
}
}
static void Main(string[] args)
{
FooConsumer fc = new FooConsumer();
Foo f = new Foo("parent");
Func<string, IBase, string> func1 = (template, node) =>
string.Format(template, node.GetName());
Func<string, string, string> func2 = (template, name) =>
string.Format(template, name);
string s1 = fc.Consume1(f, "<li>{0}</li>", func1);
string s2 = fc.Consume2(f, "<li>{0}</li>", func2);
Console.WriteLine("Executing first:");
Console.WriteLine(s1);
Console.WriteLine("Executing second:");
Console.WriteLine(s2);
}
}
}
非常感谢,
朱塞佩
【问题讨论】:
标签: .net generics parameters casting interface