我正在尝试创建一个隐式转换,它允许我使用 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 typeT
only if all of the following are true, whereS0
andT0
are the types that result from removing the trailing?
modifiers, if any, fromS
andT
:
S0
andT0
are different types.Either
S0
orT0
is the class or struct type in which the operator declaration takes place.Neither
S0
norT0
is an interface-type.Excluding user-defined conversions, a conversion does not exist from
S
toT
or fromT
toS
.
您同时违反了第三条规则(接口(interface)类型)和第四条规则(因为已经存在从 MyCollection
到 IEnumerable<MyType>
的非用户定义转换)。
如果允许的话,我还是建议不要这样做。
只有在效果非常明显时才应使用隐式转换(对于具有一定语言知识的人):很明显 long x = 3 + 5
是什么在类型转换中做int
至 long
,非常明显的是什么 object x = "abc"
在类型转换中做string
至 object
.
除非您使用 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/