Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 隐式从列表中删除泛型参数<;T>;_C# - Fatal编程技术网

C# 隐式从列表中删除泛型参数<;T>;

C# 隐式从列表中删除泛型参数<;T>;,c#,C#,TL;DR:(标题给出了它)我能在一次转换中“隐式地从列表中删除泛型参数吗?” 今天一位朋友问我是否可以将列表隐式转换为非通用包装 var list = new List<_some_type_>(); ObjectResult result = list; 而不是 class ObjectResult { ... } 我们对用户定义转换的限制是(我是否缺少任何限制?) 无法转换为基类型或从基类型转换 无法转换到接口或从接口转换 必须将转换包含在两种类型之一中 是什么让列表变得如

TL;DR:(标题给出了它)我能在一次转换中“隐式地从
列表中删除泛型参数吗?”

今天一位朋友问我是否可以将
列表
隐式转换为非通用包装

var list = new List<_some_type_>();
ObjectResult result = list;
而不是

class ObjectResult { ... }
我们对用户定义转换的限制是(我是否缺少任何限制?)

  • 无法转换为基类型或从基类型转换
  • 无法转换到接口或从接口转换
  • 必须将转换包含在两种类型之一中
  • 是什么让列表变得如此困难:

  • 列表
    的唯一派生来自
    对象
    ;因此,我们必须直接从
    List
  • List
    只有接口,而且必须直接从
    List
  • 列表
    显然是在框架中编译的,因此,它必须来自我们的包装器
  • 我想到了一个两步解决方案,其中有一个我们可以转换的中间人(而只有
    列表
    的中间人是
    对象
    ,根据规则1,这不是一个选项)

    公共类ObjectResult
    {
    公共静态隐式运算符ObjectResult(WrapperBase arg){…}
    }
    公共类包装器基{}
    公共类ObjectResultRapper:WrapperBase
    {
    公共静态隐式运算符ObjectResultRapper(列表参数){…}
    }
    
    然后,调用代码如下所示:

    public static implicit operator ObjectResult(List<T> list) { ... }
    
    var list = new List<int>();
    ObjectResultWrapper<int> wrap = list;
    ObjectResult result = wrap;
    
    public class ObjectResult
    {
        //...
        public static ObjectResult From<T>(T arg) { return new ObjectResult<T>(arg); }
        //...
    }
    public class ObjectResult<T> : ObjectResult
    {
        //...
        public ObjectResult(T obj) { /* ... some implementation ... */ }
        //...
    }
    
    var list=newlist();
    ObjectResultRapper wrap=列表;
    ObjectResult=wrap;
    
    这并不能真正解决问题,它只是隐式删除
    t
    的一种变通方法(但分两步,而不是一步)。在这一点上,有一个helper方法会更容易,而不使用用户定义的转换


    可能有人反对隐式删除通用论点的目标——我不知道他为什么认为这很重要。考虑这只是一个学术问题。

    答案:<强>不,不能用隐式转换来实现。< /强>

    备选方案:

    我认为最好是一个静态
    ObjectWrapper.FromList(List)
    方法


    包装器强制转换也是一个选项,尽管没有那么优雅。

    不如声明一个静态的“Convert”函数,而不是尝试声明一个转换运算符?然后,您可以使用编译器的类型推断执行如下操作(从
    调用转换方法
    ):


    不能从任何接口转换似乎是一个非常奇怪的要求<代码>列表
    实现了非泛型的IList,它不需要
    知识。我希望您指出了对该语言的要求-这些不是我编造的。。。只是澄清一下你的评论是针对语言的,而不是我:)你能解释一下你到底想做什么吗?
    ObjectResult
    的意义是什么?我不明白——如果您想要一个从通用
    列表派生的非通用列表
    ,为什么不作为
    IList
    与之交互?这正是它的目的。@svick和KirkWoll再一次,我在学术上接近这个目标,不是因为某个结果目标。这是一个平淡的问题,寻找平淡的答案(是否可能…)。是的,有IList,但问题不是“是否存在
    列表
    的非泛型句柄?”在我的第二条规则中,我提到了不允许接口转换,至少这是我从编译器得到的:“Testing.ObjectResult.implicit operator Testing.ObjectResult(System.Collections.generic.IEnumerable)“:不允许与接口进行用户定义的转换。我使用的是.net 4.0和visual studio 2010compiler@payo:嗯,看来你不能那么做。更新的答案。我同意静态方法可能是这里最好的解决方案。但我不建议使用双重强制转换,它太复杂和混乱了。我同意更优雅的解决方案是使用实用程序(比如静态强制转换)。但同样,这个问题更多的是在语言中寻找什么是可能的。我为我的固执道歉——但我已经说过很多次了,所以人们总是想修正你的方法,而不是回答问题。有时候我们只是在寻找可能的东西,即使我们的测试用例很差。@payo:我也注意到了,我真的很讨厌人们不起来回答问题。在这种情况下,qestion似乎是不可能的。我同意这是一个更优雅的解决方案。看来,这个问题的具体目标是不可能实现的。
    var list = new List<int>();
    ObjectResultWrapper<int> wrap = list;
    ObjectResult result = wrap;
    
    List<int> list = new List<int>();
    ObjectResult result = ObjectResult.From(list);
    
    public class ObjectResult
    {
        //...
        public static ObjectResult From<T>(T arg) { return new ObjectResult<T>(arg); }
        //...
    }
    public class ObjectResult<T> : ObjectResult
    {
        //...
        public ObjectResult(T obj) { /* ... some implementation ... */ }
        //...
    }