2017-06-08 19 views
0

我有一个通用的包装类型的可变数量的包装类型:解开在单个操作中

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(); 

看看我需要多次解开包装才能得到条带g里面。

我想要的是写一个强类型的通用操作,可以在单个步骤(或步数不变)中进行解包。 一些可能有用的工具是泛型方法,lambda表达式,方法重载。我甚至想过从定点组合器构建基于类型的Y-combinatory以用于无限递归。但即使递归也需要步骤/循环/迭代。

我不确定这是否可以解决,但C#的类型推断可以解决NP难题(请参阅https://blogs.msdn.microsoft.com/ericlippert/2007/03/28/lambda-expressions-vs-anonymous-methods-part-five/),所以我仍然有一个很小的机会可以忽略它。

+0

疑问,你可以做,没有添加过载每个缠绕级别('展开(这个Wrap > wrapping)'etc)。这种情况下是否有真实世界的用法? – Evk

+0

@Evk“每个包装级别的重载”可能只有一种方法只能使用对数级数,但对我而言这并不太有趣。例如,当你想要反转一个基于元组的多类型链表时,需要类似的技巧。 –

+0

嗯,我想你想要的只是C#类型系统不可能实现的。 “ – Evk

回答

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(); 
     } 
    } 
} 
+0

”的步骤数不是固定的“ - 对于我来说,当您调用”.FullUnwrap()“时,您的解决方案具有不变的调用步骤数,因为您在1步中进行解包。不幸的是,严格的打字被违反。例如,我的'wrappedString.Unwrap()..... Unwrap()==“ssss”'将编译/工作与s ==“ssss”'相同,但是您的'wrappedString.FullUnwrap()== “ssss”'不会编译或工作相同。 –

+0

真的,很好的电话。 – mjwills