在单个操作中展开可变数量的包装类型

时间:2017-06-08 12:08:37

标签: c# types type-inference

我有一个通用的包装类型:

public class Wrap<T> {
    public T Contents { get; set; }
}

我可以将任何对象包装在包装中或打开包装对象:

public static class WrapHelpers {
    public static Wrap<T> Wrap<T>(this T contents) {
        return new Wrap<T> { Contents = contents };
    }
    public static T Unwrap<T>(this Wrap<T> wrapped) {
        return wrapped.Contents;
    }
    //NOP
    public static T Unwrap<T>(this T contents) {
        return contents;
    }
}

这是我如何包装和打开一些字符串:

string s = "ssss";
var wrappedString = s.Wrap().Wrap().Wrap();
string unwrappedString = wrappedString.Unwrap().Unwrap().Unwrap().Unwrap().Unwrap().Unwrap();

了解我需要多次展开以获取内部字符串。

我想要的是编写一个强类型的泛型操作,可以在一个步骤(或常数步骤)中进行解包。 一些可能有用的工具是泛型方法,lambdas,方法重载。我甚至考虑过用定点组合器构建基于类型的Y组合来用于无限递归。甚至递归也需要步骤/周期/迭代。

我不确定这是否可以解决,但C#的类型推断可以解决NP难问题(参见https://blogs.msdn.microsoft.com/ericlippert/2007/03/28/lambda-expressions-vs-anonymous-methods-part-five/)所以我仍然很难忽略某些东西。

1 个答案:

答案 0 :(得分:0)

这可能会有效,但是你会失去类型安全性,而且肯定不是一定数量的步骤:(

using System;
using System.Collections.Generic;
using System.Linq;


namespace Test
{
    public class Wrap<T>
    {
        public T Contents { get; set; }

        public object DeepUnwrap()
        {
            var wrapped = this;
            var hello = wrapped.Unwrap();

            if (hello != null)
            {
                var type = hello.GetType();

                if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Wrap<>))
                    return ((dynamic)hello).DeepUnwrap();
            }

            return hello;
        }

    }

    public static class WrapHelpers
    {
        public static Wrap<T> Wrap<T>(this T contents)
        {
            return new Wrap<T> { Contents = contents };
        }
        public static T Unwrap<T>(this Wrap<T> wrapped)
        {
            return wrapped.Contents;
        }

        public static object FullUnwrap<T>(this Wrap<T> wrapped)
        {
            var hello = wrapped.DeepUnwrap();

            return hello;
        }

        //NOP
        public static T Unwrap<T>(this T contents)
        {
            return contents;
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            string s = "ssss";
            var wrappedString = s.Wrap().Wrap().Wrap();
            Console.WriteLine(wrappedString.FullUnwrap());
            Console.ReadLine();
        }
    }
}