Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.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# 传递函数<;T、 TResult>;TResult未知的地方_C#_Generics_Lambda - Fatal编程技术网

C# 传递函数<;T、 TResult>;TResult未知的地方

C# 传递函数<;T、 TResult>;TResult未知的地方,c#,generics,lambda,C#,Generics,Lambda,注意:请适当地重新标记和/或重新命名 我有一个类,FooEnumerator,它包装了一个Foo,并实现了IEnumerable。Foos表示树状数据结构,枚举的FooEnumerators是当前节点的子节点 Foo是供应商提供的数据对象FooEnumerator实现一组自定义筛选代码 class FooEnumerator : IEnumerable<FooEnumerator> { public Foo WrappedNode { get; private set; }

注意:请适当地重新标记和/或重新命名


我有一个类,
FooEnumerator
,它包装了一个
Foo
,并实现了
IEnumerable
Foo
s表示树状数据结构,枚举的
FooEnumerator
s是当前节点的子节点

Foo
是供应商提供的数据对象
FooEnumerator
实现一组自定义筛选代码

class FooEnumerator : IEnumerable<FooEnumerator>
{
    public Foo WrappedNode { get; private set; }
    public string Name { get { return WrappedNode.Name; } }
    public int Id { get{ return WrappedNode.Id; } }
    public DateTime Created { get{ return WrappedNode.Created; } }

    public FooEnumerator(Foo wrappedNode)
    {
        WrappedNode = wrappedNode;
    }

    public IEnumerator<FooEnumerator> GetEnumerator()
    {
          foreach (Foo child in this.GetChildren())
              if(FilteringLogicInHere(child))
                    yield return new FooEnumerator(child);
    }

    ...
}
其中,
TKey
是给定的
Func
的返回类型,但是方法签名中的类型参数,在编译时计算出来

示例用法

var x = GetStartingNode();

var sort = n => n.DateTime;
var enu = new FooEnumerator(x, sort);

var sort2 = n => n.Name;
var enu2 = new FooEnumerator(x, sort2);
然后,排序表达式将存储在类变量中,
FooEnumerator
的工作方式如下:

// pseudo-implementation

private Expression<Func<Foo, TKey>> _sortBy;

public FooEnumerator(Foo wrappedNode, Expression<Func<Foo, TKey>> sortBy)
{
    WrappedNode = wrappedNode;
    _sortBy = sortBy;
}

public IEnumerator<FooEnumerator> GetEnumerator()
{
    foreach (Foo child in this.GetChildren().OrderBy(_sortBy))
        if(FilteringLogicInHere(child))
            yield return new FooEnumerator(child);
}
//伪实现
私密的表达;
公共FooEnumerator(Foo wrappedNode,表达式排序)
{
WrappedNode=WrappedNode;
_sortBy=sortBy;
}
公共IEnumerator GetEnumerator()
{
foreach(this.GetChildren().OrderBy(_sortBy))中的Foo-child
if(过滤器glogicinhere(儿童))
返回新的FooEnumerator(子项);
}
如何在此用例中指定TKey的类型(隐式或显式)?


我不想硬编码,因为我希望能够对底层
Foo
的任何和所有属性进行排序

嗯,您不能创建类型为
Expression
的成员委托变量,因为从未指定
TKey
。但是,您可以创建一个类型为
Expression
的成员,该类型可能满足您的需要。当然,您可能需要更改
FooEnumerator
构造函数以接受此签名

编辑:其他人建议参数化
FooEnumerator
,以便它接受
TKey
。您当然可以这样做,但您应该了解出现的问题:

  • 通过对枚举数进行参数化,您就等于是在浪费时间。任何想要存储
    FooEnumerator
    的代码都必须事先知道类型
    T
    。但是,您可以实现一个非通用接口
    IFooEnumerator
    ,来处理这个问题
  • 如果您希望将来支持对多个字段进行排序,则参数化枚举数会产生问题。C#不支持类型参数数目可变的泛型,这会限制需要多个任意类型的泛型的创建。这个问题更难处理,因为开始创建
    FooEnumerator
    FooEnumerator
    FooEnumerator
    ,等等都很麻烦

  • 当然,您不能创建类型为
    Expression
    的成员委托变量,因为从未指定
    TKey
    。但是,您可以创建一个类型为
    Expression
    的成员,该类型可能满足您的需要。当然,您可能需要更改
    FooEnumerator
    构造函数以接受此签名

    编辑:其他人建议参数化
    FooEnumerator
    ,以便它接受
    TKey
    。您当然可以这样做,但您应该了解出现的问题:

  • 通过对枚举数进行参数化,您就等于是在浪费时间。任何想要存储
    FooEnumerator
    的代码都必须事先知道类型
    T
    。但是,您可以实现一个非通用接口
    IFooEnumerator
    ,来处理这个问题
  • 如果您希望将来支持对多个字段进行排序,则参数化枚举数会产生问题。C#不支持类型参数数目可变的泛型,这会限制需要多个任意类型的泛型的创建。这个问题更难处理,因为开始创建
    FooEnumerator
    FooEnumerator
    FooEnumerator
    ,等等都很麻烦

  • 您还可以参数化枚举数:

    class FooEnumerator<TKey> {
    
      // ... All your 'pseudo' code would work here
    
    }
    
    类枚举器{
    //…您所有的“伪”代码都可以在这里工作
    }
    

    我建议使用
    IComparable
    对接口进行编程。

    您也可以参数化枚举器:

    class FooEnumerator<TKey> {
    
      // ... All your 'pseudo' code would work here
    
    }
    
    类枚举器{
    //…您所有的“伪”代码都可以在这里工作
    }
    
    但是,我建议使用
    IComparable
    对接口进行编程