c# - 从 IEnumerable<T> 到 MyCollection 的隐式转换

标签 c# casting

我正在尝试创建一个隐式转换,它允许我使用 LINQ 结果直接返回 MyCollection

public class MyCollection : ICollection<MyType> 
{
    private List<MyType> _list = new List<MyType>();

    public MyCollection(IEnumerable<MyType> collection) 
    {
        _list = new List<MyType>(collection);
    }

    public static implicit operator MyCollection(IEnumerable<MyType> collection) 
    {
        return new MyCollection(collection);
    }

    // collection methods excluded for brevity

    public MyCollection Filter(string filter) 
    {
        return _list.Where(obj => obj.Filter.Equals(filter)); // cannot implicitly convert
    }
}

我以前没有尝试过使用隐式用户定义的转换,我做错了什么?

最佳答案

您不能使用 implicit当类型转换自或类型转换为接口(interface)类型时。 (如果一种类型派生自另一种类型,则也不允许使用它们,因此 object 一直是允许的)。事实上,你不被允许explicit在这种情况下。来自 ECMA-364 的第 17.9.3 节:

A class or struct is permitted to declare a conversion from a source type S to a target type T only if all of the following are true, where S0 and T0 are the types that result from removing the trailing ? modifiers, if any, from S and T:

  • S0 and T0 are different types.

  • Either S0 or T0 is the class or struct type in which the operator declaration takes place.

  • Neither S0 nor T0 is an interface-type.

  • Excluding user-defined conversions, a conversion does not exist from S to T or from T to S.

您同时违反了第三条规则(接口(interface)类型)和第四条规则(因为已经存在从 MyCollectionIEnumerable<MyType> 的非用户定义转换)。

如果允许的话,我还是建议不要这样做。

只有在效果非常明显时才应使用隐式转换(对于具有一定语言知识的人):很明显 long x = 3 + 5 是什么在类型转换中做intlong ,非常明显的是什么 object x = "abc"在类型转换中做stringobject .

除非您使用 implicit具有类似级别的“显而易见”,那么这是一个坏主意。

特别是,通常隐式转换不应该在相反的方向上隐式,而是应该在一个方向上隐式(大多数内置情况下的“扩大”方向)和相反方向上的显式(“缩小”方向) “方向)。由于您已经从 MyCollection 获得了隐式转换至 IEnumerable<MyCollection> , 在相反方向上使用隐式转换几乎是个坏主意。

更一般地说,由于您在谈论 Linq 的使用,因此使用可扩展的 ToMyCollection() 有更大的好处。方法,因为那时您将遵循 ToArray() 的 Linq 约定, ToList()等:

public static class MyCollectionExtensions
{
  public static MyCollection ToMyCollection(this IEnumerable<MyType> collection) 
  {
      return collection as MyCollection ?? new MyCollection(collection);
  }
}

请注意,我测试的是集合已经是 MyCollection 的情况避免浪费的重复 build 。您可能也可能不想处理 List<MyType> 的情况。特别是使用内部构造函数将其分配给 _list直接。

但是,在这样做之前,您需要考虑允许的混叠效果。如果您知道别名不会导致问题,这可能是一个非常有用的技巧(或者该类仅在内部使用并且已知别名不是问题,或者别名不会损害 MyCollection 的使用,或者别名实际上是可取的)。如果有疑问,那么就用方法做 return new MyCollection(collection)更安全。

关于c# - 从 IEnumerable<T> 到 MyCollection 的隐式转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22402329/

相关文章:

c# - 在 webapi 中正确使用 await async

C++ 获取句柄字符串值

java - 在 Java 中为具有类型参数的类编写平等契约

kotlin - Kotlin/Java 中的简单转换

C# 从 powershell 脚本获取变量

c# - .Net 类来控制远程机器上的服务?

c# - 消除 LET 运算符和 SqlFunctions

java.lang.ClassCastException : java. lang.String JSON Tokener android

java - 使用 gson 反序列化时将 TypeToken 转换为 Type 时出错

c# - 像画廊一样的组合框下拉菜单