覆盖ToString或为接口提供非ToString命名扩展方法?

Jam*_*ndt 4 c#

我的问题是关于命名,设计和实现的选择.我可以看到自己走向两个不同的方向,如何解决问题,我很想知道其他可能遇到类似问题的人会处理这个问题.它是部分美学,部分功能.

关于代码的一点背景......我创建了一个名为的类型ISlice<T>,它提供了对项目源的一部分的引用,这些项目可以是一个集合(例如数组,列表)或字符串.核心支持来自一些实现类,这些类支持快速索引,使用切片的Begin和End标记从原始源获取项目.目的是提供类似于Go语言提供的切片功能,同时使用Python样式索引(即支持正负索引).

为了使创建切片(实例ISlice<T>)更容易和更"流畅",我创建了一组扩展方法.例如:

static public ISlice<T> Slice<T>(this IList<T> source, int begin, int end)
{
  return new ListSlice<T>(source, begin, end);
}

static public ISlice<char> Slice(this string source, int begin, int end)
{
  return new StringSlice(source, begin, end);
}
Run Code Online (Sandbox Code Playgroud)

还有其他一些,例如提供可选的开始/结束参数,但上面的内容足以满足我的需求.

这些例程运行良好,可以轻松切片集合或字符串.我还需要的是获取切片并将其创建为数组,列表或字符串的方法.这就是事情变得"有趣"的地方.最初,我认为我需要创建ToArray,ToList扩展方法,但后来记得LINQ变体在集合实现时执行优化ICollection<T>.在我的情况下,ISlice<T>它确实继承了它,虽然很多我的懊恼,因为我不喜欢从像Add这样的方法抛出NotSupportedExceptions.无论如何,我免费获得这些.大.

如果没有内置支持将一个IEnumerable<char>轻松转换回字符串,那么转换回一个字符串呢?我发现最接近的是string.Concat重载之一,但它不能尽可能高效地处理字符.从设计角度来看同样重要的是,它不会像"转换"例程一样跳出来.

第一个想法是创建一个ToString扩展方法,但这不起作用,因为ToString是一个实例方法,这意味着它胜过扩展方法,永远不会被调用.我可以覆盖ToString,但行为将是不一致的,因为ListSlice<T>特殊情况需要它的ToString,其中T是一个char.我不喜欢这样,因为当type参数是char时ToString会给出一些有用的东西,但在其他情况下是类名.此外,如果将来创建其他切片类型,我必须创建一个公共基类以确保相同的行为,或者每个类必须实现相同的检查.接口上的扩展方法可以更优雅地处理.

扩展方法引出了一个命名约定问题.显而易见的是使用ToString,但如前所述,它是不允许的.我可以把它命名为不同的东西,但是什么?ToNewString?NewString?CreateString?To-family方法中的某些东西会让它落入ToArray/ToList例程,但是当在intellisense和代码编辑器中看到时,ToNewString突然变成'奇数'.NewString/CreateString不像你必须知道的那样可以发现它们.它不符合To-family方法提供的"转换方法"模式.

去覆盖ToString并接受硬编码到ListSlice<T>实现和其他实现中的不一致行为?使用更灵活,但可能更糟糕的扩展方法路由?我还没有考虑过第三种选择吗?

我的直觉告诉我尽管保留了我的ToString但是,它也发生在我身上......你会不会考虑ToString给你一个集合/可枚举类型的有用输出?这会违反最少惊喜的原则吗?

更新

切片操作的大多数实现提供了来自用于切片的任何源的数据的副本,尽管是子集.这在大多数用例中都是完全可以接受的,因为您只需返回相同的数据类型即可获得干净的API.如果对列表进行切片,则返回一个列表,其中仅包含切片中指定范围内的项目.如果切片字符串,则返回一个字符串.等等.

我在上面描述的切片操作在处理使这种行为不合需要的约束时解决了一个问题.例如,如果使用大型数据集,则切片操作将导致不必要的额外内存分配,更不用说复制数据对性能的影响.如果在获得最终结果之前切片将对其进行进一步处理,则尤其如此.因此,切片实现的目标是引用更大的数据集,以避免对信息进行不必要的复制,直到它变得有益.

问题在于,在处理结束时,希望将基于切片的处理数据转换回更多API和.NET友好类型,如列表,数组和字符串.它使数据更容易传递到其他API.它还允许您丢弃切片,因此也可以丢弃切片引用的大数据集.

Ree*_*sey 5

您是否会考虑ToString为集合/可枚举类型提供有用的输出?这会违反最少惊喜的原则吗?

不,是的.这将是完全意外的行为,因为它的行为与每个其他集合类型不同.

至于这个:

转换回字符串怎么样,因为没有内置的支持将IEnumerable> char <轻松转换回字符串?

就个人而言,我只会使用字符串构造函数来获取数组:

string result = new string(mySlice.ToArray());
Run Code Online (Sandbox Code Playgroud)

这是显式的,理解的和期望的 - 我希望通过将对象传递给构造函数来创建新的字符串.