如何创建一个采用T或IEnumerable <t>?</t>的泛型类型

时间:2010-03-16 15:21:40

标签: c# generics

假设我有一个类型:

public class Transformer<T, TResult>
    where T : IMessage
    where TResult : IMessage
{
    private Func<T, IEnumerable<TResult>> _transformer;

    public Transformer(Func<T, TResult> transformer)
    {
        _transformer = null // ?
    }

    public Transformer(Func<T, IEnumerable<TResult>> transformer)
    {
        _transformer = transformer;
    }
}

所以从本质上讲,我想在第一个构造函数中将Func<T, TResult>转换为Func<T, IEnumerable<TResult>>

我试图创建一个私有内部类,它接受Func<T, TResult>并定义一个返回IEnumerable的方法,如下所示:

private class TransformerWrapper
{
    private readonly Func<T, TResult> _func;

    public TransformerWrapper(Func<T, TResult> func)
    {
        _func = func;
    }

    public IEnumerable<TResult> Transform<T>(T message) where T : IMessage
    {
        yield return _func(message);
    }
}

但它并没有真正发挥作用。我得到一个错误,说委托有一个无效的参数 - 无法从T转换为T.

首先,编译器错误发生了什么,其次是另一种方式吗?

更新

发布后几分钟,我找到了解决方案:

public Transformer(Func<T, TResult> transformer)
{
    _transformer = new TransformerWrapper<T, TResult>(transformer).Transform;
}

private class TransformerWrapper<T, TResult>
{
    private readonly Func<T, TResult> _func;

    public TransformerWrapper(Func<T, TResult> func)
    {
        _func = func;
    }

    public IEnumerable<TResult> Transform(T message)
    {
        yield return _func(message);
    }
}

我仍然无法理解第一个解决方案无效的原因。我需要考虑一下......

3 个答案:

答案 0 :(得分:1)

您在T函数中指定了新的泛型Transform<T>。由于TTResult已经在父类中定义,因此子类中不需要任何通用的东西。

从方法签名中删除<T>和泛型限定符,它应该编译。

public IEnumerable<TResult> Transform(T message)
{
    yield return _func(message);
}

答案 1 :(得分:1)

将内部课程更改为:

    private class TransformerWrapper
    {
        private readonly Func<T, TResult> _func;

        public TransformerWrapper(Func<T, TResult> func)
        {
            _func = func;
        }

        public IEnumerable<TResult> Transform(T message)
        {
            yield return _func(message);
        }
    }
}

编译已经知道T是什么,并且您不需要再次约束该方法。

答案 2 :(得分:1)

试试这个:

public Transformer(Func<T, TResult> transformer)
{
    _transformer = t => Convert(t, transformer);
}

private static IEnumerable<TResult> Convert(T value, Func<T, TResult> transformer)
{
    yield return transformer(t);
}