我有一些代码,它抛出。我不明白为什么。
string s="asdf";
Console.WriteLine(s[1..3]);
dynamic d="asdf";
Console.WriteLine(d[1..3]); // throws
// RuntimeBinderException: The best overloaded method match for 'string.this[int]' has some invalid arguments
是否有一些静态解析的编译器魔法?生成的 IL 表明了这一点。
callvirt System.String.Substring
有没有办法在动态声明的表达式上使用范围索引?
最佳答案
Range Indexing 在 C# 8.0 中发布,它不支持动态,它不能被翻译成另一个代码(在本例中是 text.SubString()
),这意味着无法在运行时解析.我在 Lambda Tuple 中遇到了与 dynamic
相同的问题还有 C# 8.0。
你可以查看 how this translation work在代码下方的右侧。
public class MyClass {
public class RangeIndexer
{
public string MyString { get; set; }
public char this[int index] { get => MyString[index]; }
public string this[Range range] { get => MyString[range]; }
}
public void Main() {
string s = "asdf";
Console.WriteLine(s[1..3]); // Translate to text.SubString()
dynamic d = "asdf";
Console.WriteLine("Index: " + d[1]); // Address to this[int]
//Console.WriteLine("Range1: " + d[1..3]); // Cannot translate to text.SubString() => Crashed
Console.WriteLine("Range2: " + d.Substring(1, 2)); // Local method of string
Console.WriteLine("Range3: " + $"{d}"[1..3]); // Cast as string and translate like Range1
dynamic rangeIndexer = new RangeIndexer();
rangeIndexer.MyString = "asdf";
Console.WriteLine("Range4: " + rangeIndexer[1..3]); // Address to this[range]
}
}
range indexing
在编译时被 IDE 翻译成 substring()
所以它实际上并没有在 string class
中实现,所以解释了为什么只有单个索引 d[1]
有效,因为它已被声明。
简而言之,我们有两个选择
选项1:事实上,dynamic
是使用Reflection技术来解析和抓取是否在变量,方法,..的范围内,这意味着不会再有翻译代码出现在Reflection中。因此,将 dynamic
转换为特定类型将有助于 IDE 基本上转换它们。
选项 2:对象应像 RangeIndexer
类一样实现以作为动态类型工作,以确保反射可以获取它。但几乎经典类型不支持,因此它仅适用于您自己的模型。
关于c# - 为什么范围索引对动态不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61882077/