C# 可以推断TKey吗?
我创建了一个验证器,用于检查C# 可以推断TKey吗?,c#,linq,generics,lambda,C#,Linq,Generics,Lambda,我创建了一个验证器,用于检查IList是否存在重复项。我提出了以下实施方案: namespace ConsoleApplication1 { class Program { static void Main(string[] args) { var bar = new Foo() {Bar = "buzz"}; var list = new List<Foo>() { }; //Foo h
IList
是否存在重复项。我提出了以下实施方案:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var bar = new Foo() {Bar = "buzz"};
var list = new List<Foo>() { }; //Foo has a property named Bar of type string
var validator = new Validator<Foo, string>(x => x.Bar); //I have to specify the type of Bar
validator.IsValid(list);
}
}
}
public class Foo
{
public string Bar { get; set; }
}
public class Validator<T, Tkey>
{
private readonly Func<T, Tkey> _keySelector;
public Validator(Func<T, Tkey> keySelector)
{
_keySelector = keySelector;
}
public bool IsValid(IList<T> list)
{
if (list != null && list.Count > 0)
{
if (list.GroupBy(_keySelector).Any(g => g.Count() > 1))
{
return false;
}
}
return true;
}
}
命名空间控制台应用程序1
{
班级计划
{
静态void Main(字符串[]参数)
{
var bar=newfoo(){bar=“buzz”};
var list=new list(){};//Foo有一个名为string类型的Bar属性
var validator=new validator(x=>x.Bar);//我必须指定Bar的类型
validator.IsValid(列表);
}
}
}
公开课Foo
{
公共字符串条{get;set;}
}
公共类验证器
{
专用只读功能键选择器;
公共验证器(Func密钥选择器)
{
_键选择器=键选择器;
}
公共布尔值有效(IList列表)
{
if(list!=null&&list.Count>0)
{
if(list.GroupBy(_keySelector).Any(g=>g.Count()>1))
{
返回false;
}
}
返回true;
}
}
但我不喜欢它的使用方式:我必须在施工期间指定钢筋的类型
问题是在初始化验证器时,我是否可以跳过TKey?是否可以推断出它?您可以使用扩展(工厂)方法来创建验证器。编译器将知道如何解析类型:
public static class SomeStaticClass
{
public static Validator<T,TKey> CreateValidator<T,TKey>(this IEnumerable<T> list, Func<T,TKey> keyselector)
{
return new Validator<T,TKey>(keyselector);
}
}
公共静态类SomeStaticClass
{
公共静态验证器CreateValidator(此IEnumerable列表,Func keyselector)
{
返回新的验证器(keyselector);
}
}
现在,可以使用以下各项创建验证器:
var list = new List<Foo>(); //Foo has a property named Bar of type string
var validator = list.CreateValidator(x => x.Bar); //the compiler can infer T (Foo) through the list and TKey from the returned property inside the lambda
var list=newlist()//Foo有一个名为Bar的属性,类型为string
var validator=list.CreateValidator(x=>x.Bar)//编译器可以从lambda中返回的属性通过list和TKey推断T(Foo)
您可以使用扩展(工厂)方法创建验证器。编译器将知道如何解析类型:
public static class SomeStaticClass
{
public static Validator<T,TKey> CreateValidator<T,TKey>(this IEnumerable<T> list, Func<T,TKey> keyselector)
{
return new Validator<T,TKey>(keyselector);
}
}
公共静态类SomeStaticClass
{
公共静态验证器CreateValidator(此IEnumerable列表,Func keyselector)
{
返回新的验证器(keyselector);
}
}
现在,可以使用以下各项创建验证器:
var list = new List<Foo>(); //Foo has a property named Bar of type string
var validator = list.CreateValidator(x => x.Bar); //the compiler can infer T (Foo) through the list and TKey from the returned property inside the lambda
var list=newlist()//Foo有一个名为Bar的属性,类型为string
var validator=list.CreateValidator(x=>x.Bar)//编译器可以从lambda中返回的属性通过list和TKey推断T(Foo)
您可以使用临时对象应用于通用参数:
static class Validator
{
public static ValidatorConstructor<T> Construct<T>() => new ValidatorConstructor<T>();
}
class ValidatorConstructor<T>
{
public Validator<T, TKey> WithSelector<TKey>(Func<T, TKey> selector) => new Validator<T, TKey>(selector);
}
class Validator<T, TKey>
{
public Validator(Func<T, TKey> selector)
{
}
}
静态类验证程序
{
公共静态验证器构造函数()=>新验证器构造函数();
}
类验证器构造函数
{
带选择器的公共验证器(Func选择器)=>新验证器(选择器);
}
类验证器
{
公共验证器(函数选择器)
{
}
}
用法:
Validator<Foo, Bar> e = Validator.Construct<Foo>().WithSelector(x => x.Bar);
Validator e=Validator.Construct().WithSelector(x=>x.Bar);
您可以使用临时对象应用于通用参数:
static class Validator
{
public static ValidatorConstructor<T> Construct<T>() => new ValidatorConstructor<T>();
}
class ValidatorConstructor<T>
{
public Validator<T, TKey> WithSelector<TKey>(Func<T, TKey> selector) => new Validator<T, TKey>(selector);
}
class Validator<T, TKey>
{
public Validator(Func<T, TKey> selector)
{
}
}
静态类验证程序
{
公共静态验证器构造函数()=>新验证器构造函数();
}
类验证器构造函数
{
带选择器的公共验证器(Func选择器)=>新验证器(选择器);
}
类验证器
{
公共验证器(函数选择器)
{
}
}
用法:
Validator<Foo, Bar> e = Validator.Construct<Foo>().WithSelector(x => x.Bar);
Validator e=Validator.Construct().WithSelector(x=>x.Bar);
您可以使用泛型扩展方法,它需要一个单独的静态类。泛型方法可以从其参数派生T型
以下是如何:
public static class Extensions
{
public static Validator<T, TKey> GetValidatorFor<T, TKey>(this List<T> list, Func<T, TKey> getter) where T : class
{
return new Validator<T, TKey>(getter);
}
}
公共静态类扩展
{
公共静态验证器getValidator for(此列表,Func getter),其中T:class
{
返回新的验证器(getter);
}
}
然后你可以这样使用它:
var list = new List<Foo>();
var validator = list.GetValidatorFor(x => x.Bar);
var list=newlist();
var validator=list.GetValidatorFor(x=>x.Bar);
您可以使用泛型扩展方法,它需要一个单独的静态类。泛型方法可以从其参数派生T型
以下是如何:
public static class Extensions
{
public static Validator<T, TKey> GetValidatorFor<T, TKey>(this List<T> list, Func<T, TKey> getter) where T : class
{
return new Validator<T, TKey>(getter);
}
}
公共静态类扩展
{
公共静态验证器getValidator for(此列表,Func getter),其中T:class
{
返回新的验证器(getter);
}
}
然后你可以这样使用它:
var list = new List<Foo>();
var validator = list.GetValidatorFor(x => x.Bar);
var list=newlist();
var validator=list.GetValidatorFor(x=>x.Bar);
首先,您的代码甚至没有编译,没有无参数构造函数,IsValid
没有lambda。我不完全同意这个问题的“标记为重复”。另一篇文章询问为什么构造函数中不可能进行类型推断。这个问题是有没有别的办法。其中有一个工厂方法(在其他帖子的问题中实际提到过),因此,对于记录:)使用扩展方法:public static类SomeStaticClass{public static Validator GetValidator(这个IEnumerable列表,Func keyselector){返回新的验证器(keyselector);}
您可以简单地使用:var list=new list()//Foo有一个名为Bar的属性,类型为string var validator=list.GetValidator(x=>x.Bar)//编译器从列表中知道T(Foo),从返回的属性中知道TKey
重新打开让我很难过。这个问题很好地解释了为什么这是不可能的,并且这个问题本身已经提供了一个解决方法:使用静态工厂方法,因为它适用于方法。“我已经输入了答案”不是重新打开的理由。当然,请作为副本再次关闭。@CodeCaster回想起来,我同意你的看法。我被注释中的代码模糊弄得心烦意乱,决定重新打开,以便至少得到更好的版本。首先,你的代码甚至没有编译,没有无参数构造函数,IsValid
不需要lambda。我不完全同意这个问题的“标记为重复”。另一篇文章询问为什么构造函数中不可能进行类型推断。这个问题是有没有别的办法。那是什么