在 F# 中的 C# 派生 类 之间进行转换
casting between C# derived classes, in F#
我有两种来自 C# 库的类型:
一个是这样定义的(只有签名):
public class CallResult<T>: CallResult
{
public CallResult([AllowNull]T data, Error? error): base(error)
public static implicit operator bool(CallResult<T> obj)
public bool GetResultOrError([MaybeNullWhen(false)] out T data, [NotNullWhen(false)] out Error? error)
public new static WebCallResult<T> CreateErrorResult(Error error)
}
第二个派生自它:
public class WebCallResult<T>: CallResult<T>
{
public HttpStatusCode? ResponseStatusCode { get; set; }
public IEnumerable<KeyValuePair<string, IEnumerable<string>>>? ResponseHeaders { get; set; }
public WebCallResult(HttpStatusCode? code, IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders, [AllowNull] T data, Error? error): base(data, error)
public WebCallResult(WebCallResult<T> callResult): base(callResult.Data, callResult.Error)
public static WebCallResult<T> CreateFrom<Y>(WebCallResult<Y> source) where Y : T
public static WebCallResult<T> CreateErrorResult(HttpStatusCode? code, IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders, Error error)
}
他们都来自:
public class CallResult
{
public Error? Error { get; internal set; }
public bool Success => Error == null;
public CallResult(Error? error)
public static implicit operator bool(CallResult obj)
public static WebCallResult CreateErrorResult(Error error)
}
一些 api 调用 return CallResult,其他 return WebCallResult。
现在我用两次相同的代码来处理它:
// turn a webcall result into a Result object
let processResultWeb (applyOnOk: 'a -> 'b) (result: WebCallResult<'a>) =
match result.Success with
| true -> Result.Ok (applyOnOk result.Data)
| false -> Result.Error (decodeError result.Error)
// turn a webcall result into a Result object
let processResult (applyOnOk: 'a -> 'b) (result: CallResult<'a>) =
match result.Success with
| true -> Result.Ok (applyOnOk result.Data)
| false -> Result.Error (decodeError result.Error)
这没有任何意义,因为它是相同的代码,而且我只关心来自基础 class (CallResult) 的数据。
所以我想将这两种类型都转换为基础 class:
let a: WebCallResult = ...
let r = a :> CallResult
但这会导致编译器错误:
[FS0001] The type 'CallResult' is not compatible with the type 'WebCallResult<'a>'
如何通过仅从它们的基础 class 访问字段来检查两种类型的结果,但使用相同的通用类型。
编辑:
classes 的源代码在这里:https://pastebin.com/mrw5W7xk
问题是我想从:
WebCallResult<'a'> to CallResult<'a>
通用似乎是问题所在。
使用您的代码,即使使用泛型,我也可以毫无问题地进行转换。这是一个例子:
let foo x =
WebCallResult<_>(System.Nullable(), Array.empty, x, Error())
let a : WebCallResult<int> = foo 3
let r = a :> CallResult<_>
let b : WebCallResult<string> = foo "str"
let q = b :> CallResult<_>
我有两种来自 C# 库的类型:
一个是这样定义的(只有签名):
public class CallResult<T>: CallResult
{
public CallResult([AllowNull]T data, Error? error): base(error)
public static implicit operator bool(CallResult<T> obj)
public bool GetResultOrError([MaybeNullWhen(false)] out T data, [NotNullWhen(false)] out Error? error)
public new static WebCallResult<T> CreateErrorResult(Error error)
}
第二个派生自它:
public class WebCallResult<T>: CallResult<T>
{
public HttpStatusCode? ResponseStatusCode { get; set; }
public IEnumerable<KeyValuePair<string, IEnumerable<string>>>? ResponseHeaders { get; set; }
public WebCallResult(HttpStatusCode? code, IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders, [AllowNull] T data, Error? error): base(data, error)
public WebCallResult(WebCallResult<T> callResult): base(callResult.Data, callResult.Error)
public static WebCallResult<T> CreateFrom<Y>(WebCallResult<Y> source) where Y : T
public static WebCallResult<T> CreateErrorResult(HttpStatusCode? code, IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders, Error error)
}
他们都来自:
public class CallResult
{
public Error? Error { get; internal set; }
public bool Success => Error == null;
public CallResult(Error? error)
public static implicit operator bool(CallResult obj)
public static WebCallResult CreateErrorResult(Error error)
}
一些 api 调用 return CallResult,其他 return WebCallResult。
现在我用两次相同的代码来处理它:
// turn a webcall result into a Result object
let processResultWeb (applyOnOk: 'a -> 'b) (result: WebCallResult<'a>) =
match result.Success with
| true -> Result.Ok (applyOnOk result.Data)
| false -> Result.Error (decodeError result.Error)
// turn a webcall result into a Result object
let processResult (applyOnOk: 'a -> 'b) (result: CallResult<'a>) =
match result.Success with
| true -> Result.Ok (applyOnOk result.Data)
| false -> Result.Error (decodeError result.Error)
这没有任何意义,因为它是相同的代码,而且我只关心来自基础 class (CallResult) 的数据。
所以我想将这两种类型都转换为基础 class:
let a: WebCallResult = ...
let r = a :> CallResult
但这会导致编译器错误:
[FS0001] The type 'CallResult' is not compatible with the type 'WebCallResult<'a>'
如何通过仅从它们的基础 class 访问字段来检查两种类型的结果,但使用相同的通用类型。
编辑: classes 的源代码在这里:https://pastebin.com/mrw5W7xk
问题是我想从:
WebCallResult<'a'> to CallResult<'a>
通用似乎是问题所在。
使用您的代码,即使使用泛型,我也可以毫无问题地进行转换。这是一个例子:
let foo x =
WebCallResult<_>(System.Nullable(), Array.empty, x, Error())
let a : WebCallResult<int> = foo 3
let r = a :> CallResult<_>
let b : WebCallResult<string> = foo "str"
let q = b :> CallResult<_>