C# 这是对';动态';?

C# 这是对';动态';?,c#,C#,在IsUnixNewline方法中,下面使用的“dynamic”是好的还是坏的 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 (IsUn

在IsUnixNewline方法中,下面使用的“dynamic”是好的还是坏的

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');
    }
}
使用系统;
班级计划
{
静态void Main()
{
字节[]字节={32,32,32,10};
string text=“hello\n”;
for(int i=0;i
在我看来,这很糟糕,因为

        var b = IsUnixNewline(new NewObjectNotSupportingIndexer(), 0);
将在开发期间完美地通过编译器,但在运行时失败。
为什么要牺牲类型安全,而你没有太多?如果您在developemt(ComInterop)期间不知道类型,那么Dynamic非常有帮助,但在这种情况下,我认为它造成的损害比help更大。

Dynamic关键字导致运行时类型检查,而不是compiletime类型检查。我一辈子都不明白为什么这个简单的操作显式地需要运行时类型检查。如果没有动力,也很容易做到这一点。我不知道我是否会将其归类为对动态的滥用,我肯定会将其归类为不必要的。

我会说“是”-
动态在这里不是必需的,并且增加了很多关于它在运行时将做什么的不确定性(当然,还丢弃了静态编译器检查);在这种情况下,最好只使用一些重载,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
。 在将
字节[]
转换为
字符串
时,您需要注意正确的编码,但您应该了解这一点

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');
    }
}
使用系统;
班级计划
{
静态void Main()
{
字节[]字节={32,32,32,10};
string text=“hello\n”;
char[]characterArray=System.Text.Encoding.ASCII.GetString(bytes.toCharray();
for(int i=0;i
首先,必须认识到
字节
不是字符。因此,要转换它们,您需要首先应用编码(即使这只是
ASCII
Default
编码)。使用
Encoding
GetString
方法将得到一个字符串,从而使这两种类型之间的区别无效

但是,为了更一般地回答,您应该始终尝试并查看这些类型的共同点。例如,
char[]
string
都实现了
IEnumerable
。因此,与其检查每个位置是否为单位换行符,为什么不使用枚举器检查所有字符的方法

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;
    }
}
使用系统;
使用系统文本;
使用System.Collections.Generic;
班级计划{
静态void Main(){
字节[]字节={32,32,32,10};
string text=“hello\n”;
if(HasUnixNewline(Encoding.ASCII.GetChars(字节))){
WriteLine(“在'bytes'中找到Unix换行符”);
}
if(HasUnixNewline(文本)){
WriteLine(“在“text.”中找到Unix换行符);
}
}
静态布尔HasUnixNewline(IEnumerable字符){
bool-prevIsCR=false;
foreach(char-ch-in-chars){
如果((ch='\n')&(!prevIsCR)){
返回true;
}
prevIsCR=ch='\r';
}
返回false;
}
}

另一种变体是使用所谓的对象(通常是无状态的)包装原始实例并提供替代接口。在这种情况下,您可以轻松实现一个只公开读取索引器并返回字符的接口,然后在
IsUnixNewLine
方法中使用它。或者,您可以应用相同的模式来避免在我的示例中使用
编码
类,方法是编写一个适配器,该适配器实现
IEnumerable
并包装一个
IEnumerable

为什么在这种情况下是动态的,而不是char或string?我不知道IsUnixNewline如何使用char或string。@Roger字节数组和string被传递方法。再看一次。我想知道你是否可以使用Linq(即,)将字节数组转换成字符数组,从而避开整个问题。嗯,还有什么可以写IsUnixNewline的呢?我找不到像IIndexable这样的接口。