C#IredonlyList<;t>;保护瞬间被downcast颠覆,还是我遗漏了什么?
鉴于以下情况: 如果一个IReadOnly(of T)是从一个现存的可变等价物(of T)中构思出来的,那么简单地转换到可变版本就允许完全访问,并且对其他人可能依赖的对象的更改具有静态元素/计数,这是真的吗?下面的输出显示了我的“第三次注入”字符串,尽管迭代了只读集合。是否仅仅是礼貌和自我控制才禁止发布只读集合?您是否应该看到提供的接口,并承担其限制,仅由于类型而强制转换不变量?感谢您对该接口和其他类似接口的真正承诺/保证的任何澄清 编辑-这不是IReadOnlyCollectionC#IredonlyList<;t>;保护瞬间被downcast颠覆,还是我遗漏了什么?,c#,c#-4.0,collections,readonly,readonly-collection,C#,C# 4.0,Collections,Readonly,Readonly Collection,鉴于以下情况: 如果一个IReadOnly(of T)是从一个现存的可变等价物(of T)中构思出来的,那么简单地转换到可变版本就允许完全访问,并且对其他人可能依赖的对象的更改具有静态元素/计数,这是真的吗?下面的输出显示了我的“第三次注入”字符串,尽管迭代了只读集合。是否仅仅是礼貌和自我控制才禁止发布只读集合?您是否应该看到提供的接口,并承担其限制,仅由于类型而强制转换不变量?感谢您对该接口和其他类似接口的真正承诺/保证的任何澄清 编辑-这不是IReadOnlyCollection与List.
与List.AsReadOnly()的重复,因为我在问题中没有提到List.AsReadOnly(),也没有提到IReadOnlyCollection。这些是由响应者介绍的。在IReadOnly接口后面,这是一个关于潜在可变列表暴露的问题。在一些评论中有一些重叠,但是像“我实际上为它的基本可变列表(T)做了什么?”这样的问题重复了我问题的精神。不是“这两个实体在只读方面有什么区别?”因为我只提到了一个
static class Program
{
public static void Main()
{
List<string> hack = (List<string>) READONLY;
hack.Add("THIRD INJECTION");
foreach (var s in READONLY)
{
Console.WriteLine(s);
}
}
public static readonly IReadOnlyList<string> READONLY = new List<string>{"@0", "@1"};
}
静态类程序
{
公共静态void Main()
{
列表hack=(列表)只读;
添加(“第三次注入”);
foreach(变量s为只读)
{
控制台。写入线(s);
}
}
public static readonly IReadOnlyList readonly=新列表{“@0”,“@1”};
}
只读的基础集合是一个可变列表,这就是创建hack
变量时强制转换实际成功的原因READONLY
对于其任何使用者都是只读的,但基础列表仍然可以更改
更新:正如鲁福爵士指出的那样,通过list.AsReadOnly()
公开列表将防止强制转换。只读的底层集合是一个可变列表,这就是创建hack
变量时强制转换实际成功的原因READONLY
对于其任何使用者都是只读的,但基础列表仍然可以更改
更新:正如鲁福爵士指出的那样,通过list.AsReadOnly()
公开列表将防止硬铸。来自:
我没有意识到界面对程序员来说更像是一个松散的保护,而不是一个“const”式的变异屏障…我错误地认为,从只读到可变的向下转换是无效的转换
接口根本就不是任何形式的“保护”。这只是实现特定功能的承诺
IReadOnlyList
的好处是语义,现在,随着C#中泛型类型的变化,灵活性增强。语义优势允许您以一种表达只读取而不修改列表的意图的方式公开列表
由于类型参数可以设置为协变的,因此灵活性也随之增加。这允许从IReadOnlyList
到IReadOnlyList
的隐式转换,其中T1
继承T2
接口的实现者决定是否提供了真正的不变性。如果希望集合真正不可变,可以使用ReadOnlyCollection
作为IReadOnlyList
的实现,而不是List
。您可以将任何IList
实现传递给ReadOnlyCollection
构造函数,新对象将在不允许修改的情况下公开该IList
对象的数据(直接…当然,您总是可以通过反射进行欺骗,即使对象是真正不可变的,而不仅仅是像ReadOnlyCollection
这样的包装器)
对于任何接口,您总是只处理具有特定类型的特定对象,该类型始终实现某些功能,并且始终可以转换为原始类型以及它可能实现的任何其他接口
将接口视为某种重要的保护形式是错误的。它们不是。它们只是表示对象的功能。来源:
我没有意识到界面对程序员来说更像是一个松散的保护,而不是一个“const”式的变异屏障……我错误地认为,从只读到可变的向下转换是无效的转换
接口根本不是任何形式的“保护”,它只是实现特定功能的承诺
IReadOnlyList
的好处是语义,现在,随着C#中泛型类型的变化,它具有灵活性。语义好处允许您以一种表示只读取列表而不修改列表的方式公开列表
灵活性在于,类型参数可以是协变的。这允许从IReadOnlyList
到IReadOnlyList
的隐式转换,其中T1
继承T2
接口的实现者可以决定是否提供了真正的不可变性。如果希望集合真正不可变,可以使用ReadOnlyCollection
作为IReadOnlyList
的实现,而不是List
。您可以将任何IList
实现传递给ReadOnlyCollection
构造函数,新对象将在不允许修改的情况下公开该IList
对象的数据(直接…当然,即使对象是真正不可变的,而不仅仅是像ReadOnlyCollection
这样的包装器,您也可以通过反射进行欺骗)
对于任何接口,您总是只处理特定对象,而