我有这样的代码:
using System;
using System.Collections.Generic;
using System.Linq;
public interface IMyString
{
string Id {get;set;}
};
public class MyString : IMyString
{
public string Id {get;set;}
}
public static class Extensions
{
public static IEnumerable<IMyString> WithId(this IEnumerable<IMyString> source, string id)
{
return source.Where(x => x.Id == id);
}
}
public class Program
{
private static List<T> GetMyStrings<T>(string key, List<T> input)
where T: IMyString
{
return input.WithId(key).ToList();
}
public static void Main()
{
var foo = new List<MyString>{ new MyString { Id = "yes"}, new MyString { Id = "no" } };
var result = GetMyStrings("yes", foo);
var result2 = foo.WithId("no");
Console.WriteLine(result2);
}
}
为什么input.WithId(key).ToList()
可以,但foo.WithId("no")
会导致语法错误?有没有办法使方法GetMyStrings
起作用?
答案 0 :(得分:5)
在没有代码上下文的情况下,很难提供太多帮助,但是这两种方法的类型约束是不同的。您有两种选择:
选项1:
cdk-visually-hidden
选项2:
public static class Extensions
{
public static IEnumerable<T> WithId<T>(this IEnumerable<T> source, string id) where T: IMyString
{
return source.Where(x => x.Id == id);
}
}
这是dotnetfiddle,其中第二个选项是有效的代码段:
答案 1 :(得分:2)
这里的问题是,只要WithId()
是非泛型的,那么它可以返回的全部是IEnumerable<IMyString>
。但是,GetMyStrings()
需要返回IEnumerable
来实现IMyString
,或从 IMyString
派生的任何接口。
考虑:
public interface IMyOtherString : IMyString
{
int LOL { get; set; }
}
public class AnotherString : MyString, IMyOtherString
{
public int LOL { get; set; }
}
AnotherString
实现了IMyString
,因此就GetMyStrings()而言,此“应该”工作:将采用该参数类型并返回该返回类型。
var foo = new List<AnotherString> {
new AnotherString { Id = "yes" }, new AnotherString { Id = "no" } };
List<IMyOtherString> result = GetMyStrings("yes", foo);
问题在于,GetMyStrings()
现在必须要求WithId()
返回IEnumerable<IMyOtherString>
,但是该返回类型不会重载WithId()
。您定义的WithId()
不是一个选项:它可以使用IEnumerable<IMyOtherString>
作为参数,但随后会将枚举中的所有内容强制转换回IMyString
。
peinearydevelopment的答案(选项1是您应该使用的答案;选项2在上述情况下无效)通过将WithId()
与GetMyStrings()
放在同一类型参数页面上来解决此问题。
这是它的外观。无需返回List<T>
。如果需要,调用者可以在其上调用ToList()。
public static IEnumerable<T> WithId<T>(this IEnumerable<T> source, string id)
where T : IMyString
{
return source.Where(x => x.Id == id);
}