Anonymous method return type casting
I have an object "ConnectableProperty" that hooks up one property to another, and requires I feed it Func. Now I have 2 types at the moment - Scalar and Color. Both are castable to each other via explicit operators. For some reason I can't feed a Func<double, double, Scalar>
to Func<double, double Color>
, even though Scalar can cast to Color. What's the deal?
To clarify, i've added the code. Note that connectable properties are the "inputs". The outputs (that can be plugged in) are Methods that have that signature.
Here's ConnectableProperty
开发者_高级运维public sealed class ConnectableProperty<T> : IEquatable<T>, IGetXY<T> where T : IValue<T>
{
private T _value;
public T Value { get { return _value; } set { _value = value; } }
public INode ParentNode { get; private set; }
public ValueConnection<T> Connection { get; set; }
public INode ConnectionFrom { get { return !IsConnected ? null : Connection.FromNode; } }
public bool IsConnected { get { return Connection == null; } }
public ConnectableProperty(INode parentNode, T value)
{
ParentNode = parentNode;
_value = value;
}
public T GetXY(double x, double y)
{
return IsConnected
? Connection.FromValue(x, y)
: _value;
}
public void Connect(INode fromNode, Func<double, double, T> getXY)
{
Connection = new ValueConnection<T>(fromNode, ParentNode, getXY, this);
}
public void Disconnect()
{
Connection = null;
}
public bool Equals(T other)
{
return _value.Equals(other);
}
public static implicit operator T(ConnectableProperty<T> connectableProperty)
{
return connectableProperty._value;
}
}
And ValueConnection:
public class ValueConnection<T>
{
public INode FromNode { get; private set; }
public INode ToNode { get; private set; }
public Func<double, double, T> FromValue { get; private set; }
public ConnectableProperty<T> ToValue { get; private set; }
public ValueConnection(INode fromNode, INode toNode, Func<double, double, T> fromValue, ConnectableProperty<T> toValue)
{
// TODO: Implement INPC type thing
FromNode = fromNode;
ToNode = toNode;
FromValue = fromValue;
ToValue = toValue;
}
}
Jon is right; just to add to that:
First, the reason this doesn't work is because there is no place where the conversion exists. Suppose you have:
Func<int> f1 = ()=>1;
Func<double> f2 = f1;
Suppose that were legal. Somewhere, the C# compiler has to generate an instruction that converts an int to a double. Where? Not in the lambda; that thing has to return an int when f1 is called. But not in f2 either, because f1 is reference identical to f1. There are two possible solutions: make it illegal, or make this actually mean:
f2 = ()=>(double)f1();
so that f1 and f2 are not reference identical anymore. We've chosen the first solution.
Second, this is legal in C# 4 if the return types have an implicit reference conversion between them. We don't need to emit any instructions for an implicit reference conversion; it is legal without any special code.
No, you won't be able to perform that conversion directly, and I wouldn't expect to be able to - but you could easily write a pair of methods to perform it for you:
public Func<double, double, Scalar> ConvertFunc(Func<double, double, Color func)
{
return (x, y) => (Scalar) func(x, y);
}
public Func<double, double, Color> ConvertFunc(Func<double, double, Scalar func)
{
return (x, y) => (Color) func(x, y);
}
When you've got a delegate which is meant to return a particular type, that has to be able to be invoked directly and return a value of the appropriate type. The caller shouldn't have to know that even though they've got a Func<X>
, if they want to get an X
out of it, they'll need to cast the result to an X
.
Wouldn't do the job simply using explicit cast inside of the function body? Then u can use just one type of the function - no casting needed
精彩评论