从IEnumerable T隐式转换。到MyCollection [英] Implicit cast from IEnumerable<T> to MyCollection

查看:86
本文介绍了从IEnumerable T隐式转换。到MyCollection的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to create an implicit cast that will allow me to use a LINQ result to directly return 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
    }
}

我没有尝试使用隐式用户定义的强制转换之前,我在做什么错了?

I've not tried using implicit user-defined casting before, what am I doing wrong?

推荐答案

不允许使用隐式当类型转换为接口类型或接口类型转换为接口类型时。 (如果一种类型是从另一种类型派生而来的,则也不允许它们,例如, object 这样的条形栏永远被允许)。确实,在这种情况下,您也不允许显式。摘自 ECMA-364

You aren't allowed to use implicit when either the type cast from, or the type cast to is an interface type. (You also aren't allowed them if one type is derived from the other, which as such bars object as ever being allowed). Indeed, you aren't allowed explicit in this case either. From section §17.9.3 of ECMA-364:


允许类或结构声明从源类型 S 设置为目标类型 T 的条件是,必须满足以下所有条件,其中 S0 T0
是从 S <中删除结尾的修饰符(如果有)的结果/ code>和 T

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 T0 是不同的类型。

S0 T0 是进行操作符声明的类或结构类型。

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

S0 T0 都不是接口类型。

不包括用户定义的转换,从 S T的转换不存在或从 T S

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

您正在打破第三个规则(接口类型)和第四个规则(因为已经存在从 MyCollection IEnumerable< MyType> 的非用户定义的转换)。

You are breaking both the third rule (interface type) and the fourth (because there's a non-user-defined conversion from MyCollection to IEnumerable<MyType> already).

如果允许的话,我还是建议反对。

If it were allowed, I'd recommend against it anyway.

隐式转换只能在效果完全消失时使用明显的(对于对语言有一定了解的人):完全显而易见的是 long x = 3 + 5 在转换 int long ,并且非常明显地显示 object x = abc 在投射 string object

Implicit casts should only be used when the effect is utterly obvious (to someone with a reasonable knowledge of the language): It's utterly obvious what long x = 3 + 5 does in casting int to long, and utterly obvious what object x = "abc" does in casting string to object.

除非您使用隐含的具有相似的显而易见级别,这是个坏主意。

Unless your use of implicit is of a similar level of "obvious", then it is a bad idea.

特别是,通常隐含的类型转换不应该是隐含的方向相反,但是它们应该在一个方向(扩大方向在大多数内置情况下),并在相反的方向(缩小方向)上显示。由于您已经可以从 MyCollection IEnumerable< MyCollection> 进行隐式转换,因此在相反,这是个坏主意。

In particular, generally implicit casts should not be implicit in the opposite direction, but rather they should be implicit in one direction (the "widening" direction in most built-in cases) and explicit in the opposite direction (the "narrowing" direction). Since you've already got an implicit cast available from MyCollection to IEnumerable<MyCollection>, having an implicit cast available in the opposite direction is pretty much a bad idea.

更一般而言,由于您在谈论使用Linq,因此使用可扩展的<$ c $会有更大的好处。 c> ToMyCollection()方法,因为这样您将遵循 ToArray() ToList的Linq约定()等:

More generally, since you are talking about use of Linq, there's an even stronger benefit in using an extensible ToMyCollection() method, because then you are going to be following the Linq convention of ToArray(), ToList(), etc.:

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

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

Note that I test for the case where the collection is already MyCollection to avoid wasteful repeated constructions. You may or may not also want to handle the case of List<MyType> specially in using an internal constructor that assigned it to _list directly.

但是,在执行此操作之前,您需要考虑允许的混叠效果。如果您知道别名不会引起问题,则这可能是一个非常有用的技巧(或者该类仅在内部使用,并且已知别名不是问题,或者别名不会损害 MyCollection的使用,否则实际上应该使用别名)。如有疑问,只需让该方法执行返回新的MyCollection(collection)便会更安全。

However, you need to consider the aliasing effects that would allow before doing so. This can be a very useful trick if you know aliasing can't cause problems (either the class is only used internally and the aliasing known not to be an issue, or aliasing doesn't hurt the use of MyCollection, or the aliasing is actually desirable). If in doubt, then just have the method do return new MyCollection(collection) to be safer.

这篇关于从IEnumerable T隐式转换。到MyCollection的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆