Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 可以推断TKey吗?_C#_Linq_Generics_Lambda - Fatal编程技术网

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。我不完全同意这个问题的“标记为重复”。另一篇文章询问为什么构造函数中不可能进行类型推断。这个问题是有没有别的办法。那是什么