F#结构判别联合与C#的互操作:转换到特定情况

F#结构判别联合与C#的互操作:转换到特定情况,f#,F#,具有一个类似于 type Result<'T,'TError> = | Ok of 'T | Error of 'TError 类型结果= |当然可以 |“恐怖”的错误 您可以强制转换到C#中的一种情况,比如var error=(Result.error)Result,但它不会使用等效的结构判别联合编译 在C#互操作场景中,如何转换为结构判别式联合的特定情况?或者,在CLR类型中如何表示结构判别联合事例?您可以使用Sharplab.io查看此类型的: public

具有一个类似于

type Result<'T,'TError> =
    | Ok of 'T
    | Error of 'TError
类型结果=
|当然可以
|“恐怖”的错误
您可以强制转换到C#中的一种情况,比如
var error=(Result.error)Result
,但它不会使用等效的结构判别联合编译


在C#互操作场景中,如何转换为结构判别式联合的特定情况?或者,在CLR类型中如何表示结构判别联合事例?

您可以使用Sharplab.io查看此类型的:

public abstract class Result<T, TError> : IEquatable<Result<T, TError>>, IStructuralEquatable, IComparable<Result<T, TError>>, IComparable, IStructuralComparable
{
    public static class Tags
    {
        public const int Ok = 0;

        public const int Error = 1;
    }

    public class Ok : Result<T, TError>
    {
        internal readonly T item;

        public T Item =>item;

        internal Ok(T item) { this.item = item;}
    }

    public class Error : Result<T, TError>
    {
        internal readonly TError item;

        public TError Item => item;

        internal Error(TError item) { this.item = item; }
    }

    ...
    public int Tag  => (this is Error) ? 1 : 0;

    public bool IsOk=> this is Ok;

    public bool IsError =>this is Error;

}
不幸的是,还不可能为此编写一个详尽的开关表达式。使用相同的模式(带有具体案例的基本枚举类),因此这可能在C#9中得到修复

在C#8中,可以使用属性模式提取包含的值(结果或错误):

更新-结构

我错过了
struct
部分。在这种情况下-一个包含所有属性的平面
struct

   public struct Result<T, TError> 
    {
        public static class Tags
        {
            public const int Ok = 0;

            public const int Error = 1;
        }


        public int Tag {get;}

        public bool IsOk =>Tag == 0;

        public bool IsError=>Tag == 1;
        public T ok {get;}

        public TError error {get;}

        public static Result<T, TError> NewOk(T _ok)
        {
            return new Result<T, TError>(_ok, 0, false);
        }

        public static Result<T, TError> NewError(TError _error)
        {
            return new Result<T, TError>(_error, 1, 0);
        }

        internal Result(T _ok, int _tag, bool P_2)
        {
            this.ok = _ok;
            this.Tag = _tag;
            this.error=default;
        }

        internal Result(TError _error, int _tag, byte P_2)
        {
            this.error = _error;
            this.Tag = _tag;
            this.ok=default;
        }

}        

另一方面,这不是最直观的表达。当C#9 DU也出现时,它可能会破裂。C#9可以使用原始模式,为基类及其成员使用默认接口成员。F#编译器必须更改以使用新语法

您可以使用Sharplab.io查看此类型:

public abstract class Result<T, TError> : IEquatable<Result<T, TError>>, IStructuralEquatable, IComparable<Result<T, TError>>, IComparable, IStructuralComparable
{
    public static class Tags
    {
        public const int Ok = 0;

        public const int Error = 1;
    }

    public class Ok : Result<T, TError>
    {
        internal readonly T item;

        public T Item =>item;

        internal Ok(T item) { this.item = item;}
    }

    public class Error : Result<T, TError>
    {
        internal readonly TError item;

        public TError Item => item;

        internal Error(TError item) { this.item = item; }
    }

    ...
    public int Tag  => (this is Error) ? 1 : 0;

    public bool IsOk=> this is Ok;

    public bool IsError =>this is Error;

}
不幸的是,还不可能为此编写一个详尽的开关表达式。使用相同的模式(带有具体案例的基本枚举类),因此这可能在C#9中得到修复

在C#8中,可以使用属性模式提取包含的值(结果或错误):

更新-结构

我错过了
struct
部分。在这种情况下-一个包含所有属性的平面
struct

   public struct Result<T, TError> 
    {
        public static class Tags
        {
            public const int Ok = 0;

            public const int Error = 1;
        }


        public int Tag {get;}

        public bool IsOk =>Tag == 0;

        public bool IsError=>Tag == 1;
        public T ok {get;}

        public TError error {get;}

        public static Result<T, TError> NewOk(T _ok)
        {
            return new Result<T, TError>(_ok, 0, false);
        }

        public static Result<T, TError> NewError(TError _error)
        {
            return new Result<T, TError>(_error, 1, 0);
        }

        internal Result(T _ok, int _tag, bool P_2)
        {
            this.ok = _ok;
            this.Tag = _tag;
            this.error=default;
        }

        internal Result(TError _error, int _tag, byte P_2)
        {
            this.error = _error;
            this.Tag = _tag;
            this.ok=default;
        }

}        

另一方面,这不是最直观的表达。当C#9 DU也出现时,它可能会破裂。C#9可以使用原始模式,为基类及其成员使用默认接口成员。F#编译器必须更改以使用新语法

首先,没有等效的结构DU。编译器将强制您在切换到结构DU时为字段命名

[<Struct>]
type Result<'T,'TError> =
    | Ok of 'T
    | Error of 'TError
;;

  type Result<'T,'TError> =
  -----^^^^^^

error FS3204: If a union type has more than one case and is a struct, 
then all fields within the union type must be given unique names.

首先,没有等效的结构DU。编译器将强制您在切换到结构DU时为字段命名

[<Struct>]
type Result<'T,'TError> =
    | Ok of 'T
    | Error of 'TError
;;

  type Result<'T,'TError> =
  -----^^^^^^

error FS3204: If a union type has more than one case and is a struct, 
then all fields within the union type must be given unique names.

返回一个不同的类-base
Result
类,该类包含两个
内部
具体类。是的,当它不是struct DU时。但看起来他已经知道了。错过了
struct
和。。。哎呀。我知道当C#9问世时会出现一些互操作问题。代码完全不同。仍然可以使用模式匹配,只是与自然模式非常不同。让我们希望他们之前修复它!这两种结果完全不同,因此如果不修改F#编译器或在C#9中生成不同的代码,这将是不容易的。我看不出它会返回一个不同的类,即带有两个
内部
具体类的base
Result
类。但看起来他已经知道了。错过了
struct
和。。。哎呀。我知道当C#9问世时会出现一些互操作问题。代码完全不同。仍然可以使用模式匹配,只是与自然模式非常不同。让我们希望他们之前修复它!这两种结果完全不同,因此如果不修改F#编译器或在C#9中生成不同的代码,这将是不容易的。我不认为使用struct DUs会发生这种情况,你可以在C#8中编写一个穷举开关表达式,但感觉不自然。使用struct DUs,你可以在C#8中编写一个穷举开关表达式,但感觉不自然。
[<Struct>]
type Result<'T,'TError> =
    | Ok of 'T
    | Error of 'TError
;;

  type Result<'T,'TError> =
  -----^^^^^^

error FS3204: If a union type has more than one case and is a struct, 
then all fields within the union type must be given unique names.
[<Struct>]
type Result<'T,'TError> =
    | Ok of ok: 'T
    | Error of error: 'TError
var error = result.error;