如何从lambda表达式到自定义类的隐式转换?

时间:2014-02-24 10:26:59

标签: c# lambda implicit-conversion

我为lazy参数传递创建了一个类:

public struct LazyValue<T>
{
    private Func<T> _fetchFunction;
    private bool _fetched;
    private T _cachedValue;

    public LazyValue(Func<T> fetchFunction)
    {
        _fetchFunction = fetchFunction;
        _fetched = false;
        _cachedValue = default(T);
    }

    public LazyValue(T fixedValue)
    {
        _fetchFunction = null;
        _fetched = true;
        _cachedValue = fixedValue;
    }

    public static implicit operator LazyValue<T>(Func<T> fetchFunction)
    {
        return new LazyValue<T>(fetchFunction);
    }

    public static implicit operator LazyValue<T>(T fixedValue)
    {
        return new LazyValue<T>(fixedValue);
    }

    public T Value
    {
        get
        {
            if (_fetched) { return _cachedValue; }

            T value = default(T);

            if (_fetchFunction != null)
            {
                value = _fetchFunction();
            }

            _cachedValue = value;
            _fetched = true;

            return value;
        }
    }

    // other members omitted here
}

现在我还有一个接受此类型作为参数的方法:

public ReturnType SomeMethod(SomeType param1, LazyValue<TimeSpan> param2)

我可以使用固定值(TimeSpan实例)调用该方法而不会出现任何问题。 但似乎不可能用param2的lambda表达式调用该方法。编译器抱怨:

Cannot convert lambda expression to type 'LazyValue<System.TimeSpan>' because it
is not a delegate type

我认为这是因为编译器无法进行两步隐式转换:首先将lambda转换为Func<TimeSpan>,然后转换为LazyValue<TimeSpan>

我知道我可以通过添加显式转换来编译,例如:

SomeMethod(arg1, new Func<TimeSpan>(() => my_expression_here))

......但这样做会很痛苦。我想避免显式转换的语法开销。我真的更愿意写:

SomeMethod(arg1, () => my_expression_here)

我还可以将param2的类型更改为Func<TimeSpan>并在方法本身中转换为LazyValue,但这对我来说似乎不太优雅。

有没有办法让隐式转换为LazyValue<T>为lambdas工作?我真的很希望能够做到这一点:

TimeSpan oneHour = TimeSpan.FromHours(1);
SomeMethod(arg1, oneHour);
SomeMethod(arg1, () => Settings.Instance.GetTimeSpan("mysetting"));

1 个答案:

答案 0 :(得分:0)

你是对的,编译器不链接隐式转换,你必须明确地实例化new Func<TimeSpan>(() => my_expression_here)

来自Implicit and Explicit Conversion Operators in C#

  

转换也无法自动链接。如果您有转换为Cat和Cat键入Dog,则无法将Dog直接分配给鼠标。