【问题标题】:Covariant Casting Solution Needed需要协变铸造解决方案
【发布时间】:2012-12-11 11:30:30
【问题描述】:

我有以下代码使用自定义Maybe.cs 解决方案

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
namespace FunctionalExtensions.Specs
{
    [Microsoft.VisualStudio.TestTools.UnitTesting.TestClass]
    public class TestMaybe
    {
        class Base { }
        class A : Base { }
        class B : Base { }

        [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethod]
        public void TestCovariance()
        {
            A a = new A();
            Maybe<A> ma = a.ToMaybe();
            Maybe<A> maa;
            Base b = a;

            Maybe<Base> mb = ma;
            Maybe<Base> mbb = b.ToMaybe();


            // This works
            (mb is Some<A>).Should().BeTrue ();
            maa = (Some<A>)(mb as object);



            // This doesn't
            (mbb is Some<A>).Should().BeTrue ();
            maa = (Some<A>)(mbb as object);
        }
    }
}

Maybe.cs 实现位于Maybe Implementation in C# — Gist,粘贴到问题中有点长。基本上,我有一个实例

object

我需要在运行时检测是否可以将其转换为

Some<A>  

但是请注意,我认为这需要隐式转换才能工作。我的猜测是,我无法从接口(c# 标准的一部分)定义隐式转换,而 Some 是一个接口。有些必须是接口才能实现 协变(C# 标准的另一部分)

猜猜如何克服这个问题还是我完全被卡住了?

【问题讨论】:

  • 这个问题有点令人困惑。您说您“我需要在运行时检测是否可以将其转换为Some&lt;A&gt;”。那将是x as Some&lt;A&gt;。所以大概你的意思是别的?
  • 这和我做的是一样的。 (mb as object) as Some 我认为是等价的,但它返回 null 而不是抛出异常
  • 转换并不简单,因为我们正在处理协变类型。一般情况下这可能是不可能的。
  • 再次澄清:as 演员返回null 让您知道这是不可能的。如果您想知道是否不可能,请检查as 是否已返回null。除了这个,你还需要做什么?您的问题目前还不清楚。
  • 我知道这是不可能的。我在问如何使它成为可能。我无法编写隐式转换,因为 Some 是一个接口。

标签: c# casting covariance


【解决方案1】:

诀窍是具体化 Maybe 类。

    public static Maybe<T> Reify<T>(this Maybe<T> This)
    {
        if (!This.IsSome())
        {
            return This;
        }
        dynamic v = This.Value();
        var r = ToMaybe(v);
        return r;
    }

一旦我的 Maybe 都被具体化了,我就可以进行正常的施法了。

A a = new A();
Base b = a;
Maybe<Base> m = b.ToMaybe();

Maybe<Base> mr = m.Reify();

Maybe<A> ma;

// Will pass
ma = (Maybe<A>) mr;

// Will fail
ma = (Maybe<A>) m;

动态关键字是解开运行时类型的魔法。

【讨论】:

  • 其实上面的代码不太行。似乎将动态与通用函数一起使用会产生随机结果。有时它会具体化类型,有时它会返回 Maybe。我已经更改了我的代码以使用反射来对动态类型进行具体化,而不是使用泛型
猜你喜欢
  • 2016-03-31
  • 1970-01-01
  • 1970-01-01
  • 2023-01-26
  • 1970-01-01
  • 2017-10-02
  • 2015-06-04
  • 1970-01-01
  • 2021-12-19
相关资源
最近更新 更多