[英]Is this an abuse of 'dynamic'?
以下是使用'动态',在方法IsUnixNewline中,好还是坏?
using System;
class Program
{
static void Main()
{
byte[] bytes = { 32, 32, 32, 10 };
string text = "hello\n";
for (int i = 0; i < bytes.Length; ++i) {
if (IsUnixNewline(bytes, i)) {
Console.WriteLine("Found Unix newline in 'bytes'.");
break;
}
}
for (int i = 0; i < text.Length; ++i) {
if (IsUnixNewline(text, i)) {
Console.WriteLine("Found Unix newline in 'text'.");
break;
}
}
}
static bool IsUnixNewline(dynamic array, int index)
{
return array[index] == '\n' && (index == 0 || array[index - 1] != '\r');
}
}
我会说“是” - 这里不需要 dynamic
,并且在运行时它会做什么会增加很多不确定性(当然,抛弃静态编译器检查); 在这种情况下,最好只使用一些重载,IMO:
static bool IsUnixNewline(char[] array, int index)
{
return array[index] == '\n' && (index == 0 || array[index - 1] != '\r');
}
static bool IsUnixNewline(byte[] array, int index)
{
return array[index] == '\n' && (index == 0 || array[index - 1] != '\r');
}
static bool IsUnixNewline(string array, int index)
{
return array[index] == '\n' && (index == 0 || array[index - 1] != '\r');
}
重写( 没有编译器! )来使用char[]
而不是dynamic
。 在将byte[]
转换为string
,您需要注意正确的编码,但您应该明白这一点。
using System;
class Program
{
static void Main()
{
byte[] bytes = { 32, 32, 32, 10 };
string text = "hello\n";
char[] characterArray = System.Text.Encoding.ASCII.GetString(bytes).ToCharArray();
for (int i = 0; i < characterArray.Length; ++i) {
if (IsUnixNewline(characterArray, i)) {
Console.WriteLine("Found Unix newline in 'bytes'.");
break;
}
}
characterArray = text.ToCharArray();
for (int i = 0; i < characterArray .Length; ++i) {
if (IsUnixNewline(characterArray, i)) {
Console.WriteLine("Found Unix newline in 'text'.");
break;
}
}
}
static bool IsUnixNewline(char[] array, int index)
{
return array[index] == '\n' && (index == 0 || array[index - 1] != '\r');
}
}
在我看来,这很糟糕
var b = IsUnixNewline(new NewObjectNotSupportingIndexer(), 0);
将在开发期间完美地完成编译器,但在运行时会失败。 为什么在没有的时候牺牲类型安全? 如果你在开发过程中不知道类型(ComInterop),动态是很有帮助的,但在这种情况下,我认为它会造成比帮助更多的伤害。
dynamic关键字导致运行时类型检查而不是编译时类型检查。 我不能为我的生活看到为什么这个简单的操作显然需要运行时类型检查。 没有动态,很容易实现同样的目标。 我不知道我是否将其归类为滥用动态,我当然将其归类为不必要的。
首先,重要的是要认识到一个byte
不是一个字符。 因此,要转换那些你需要首先应用编码(即使那只是ASCII
或Default
编码)。 使用Encoding
的GetString
方法执行此操作将为您提供一个字符串,使两种类型之间的区别为void。
但是,为了更广泛地回答,您应该总是尝试看看这些类型的共同点。 例如, char[]
和string
实现了IEnumerable<char>
。 因此,为什么没有使用枚举器检查所有字符的方法,而不是检查每个位置是否为单位换行符?
using System;
using System.Text;
using System.Collections.Generic;
class Program {
static void Main() {
byte[] bytes = { 32, 32, 32, 10 };
string text = "hello\n";
if (HasUnixNewline(Encoding.ASCII.GetChars(bytes))) {
Console.WriteLine("Found Unix newline in 'bytes'.");
}
if (HasUnixNewline(text)) {
Console.WriteLine("Found Unix newline in 'text'.");
}
}
static bool HasUnixNewline(IEnumerable<char> chars) {
bool prevIsCR = false;
foreach (char ch in chars) {
if ((ch == '\n') && (!prevIsCR)) {
return true;
}
prevIsCR = ch == '\r';
}
return false;
}
}
另一种变体是使用所谓的适配器模式 ,即包装原始实例并提供替代接口的(通常是无状态的)对象。 在这种情况下,您可以轻松实现一个只暴露读索引器并返回字符的接口,然后在IsUnixNewLine
方法中使用它。 或者您可以通过编写实现IEnumerable<char>
并包装IEnumerable<byte>
的适配器来应用相同的模式以避免在我的示例中使用Encoding
类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.