gpt4 book ai didi

c# - 从接口(interface)转换为底层类型

转载 作者:太空狗 更新时间:2023-10-29 20:08:48 25 4
gpt4 key购买 nike

审查 earlier question在 SO 上,我开始考虑类将值(例如集合)公开为由值的类型实现的接口(interface)的情况。在下面的代码示例中,我使用了一个列表,并将该列表公开为 IEnumerable。

通过 IEnumerable 接口(interface)公开列表定义了仅枚举列表而不修改列表的意图。但是,由于可以将实例重新转换回列表,因此当然可以修改列表本身。

我还在示例中包含该方法的一个版本,该方法通过在每次调用该方法时将列表项引用复制到新列表来防止修改,从而防止对基础列表进行更改。

所以我的问题是,所有将具体类型公开为已实现接口(interface)的代码都应该通过复制操作来实现吗?明确指示“我想通过接口(interface)公开此值,并且调用代码只能通过接口(interface)使用此值”的语言结构是否有值(value)?当通过他们的界面公开具体值时,其他人使用什么技术来防止这些意外的副作用。

请注意,我理解所示行为是预期行为。我并不是说这种行为是错误的,只是它确实允许使用表达意图以外的功能。也许我对界面赋予了太多的重要性——将其视为功能限制。想法?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TypeCastTest
{
class Program
{
static void Main(string[] args)
{
// Demonstrate casting situation
Automobile castAuto = new Automobile();

List<string> doorNamesCast = (List<string>)castAuto.GetDoorNamesUsingCast();

doorNamesCast.Add("Spare Tire");

// Would prefer this prints 4 names,
// actually prints 5 because IEnumerable<string>
// was cast back to List<string>, exposing the
// Add method of the underlying List object
// Since the list was cast to IEnumerable before being
// returned, the expressed intent is that calling code
// should only be able to enumerate over the collection,
// not modify it.
foreach (string doorName in castAuto.GetDoorNamesUsingCast())
{
Console.WriteLine(doorName);
}

Console.WriteLine();

// --------------------------------------

// Demonstrate casting defense
Automobile copyAuto = new Automobile();

List<string> doorNamesCopy = (List<string>)copyAuto.GetDoorNamesUsingCopy();

doorNamesCopy.Add("Spare Tire");

// This returns only 4 names,
// because the IEnumerable<string> that is
// returned is from a copied List<string>, so
// calling the Add method of the List object does
// not modify the underlying collection
foreach (string doorName in copyAuto.GetDoorNamesUsingCopy())
{
Console.WriteLine(doorName);
}

Console.ReadLine();
}
}

public class Automobile
{
private List<string> doors = new List<string>();
public Automobile()
{
doors.Add("Driver Front");
doors.Add("Passenger Front");
doors.Add("Driver Rear");
doors.Add("Passenger Rear");
}

public IEnumerable<string> GetDoorNamesUsingCopy()
{
return new List<string>(doors).AsEnumerable<string>();
}
public IEnumerable<string> GetDoorNamesUsingCast()
{
return doors.AsEnumerable<string>();
}
}

}

最佳答案

防止这种情况的一种方法是使用 AsReadOnly()以防止任何此类邪恶行为。我认为真正的答案是,除了在返回类型等方面公开的接口(interface)/契约(Contract)之外,你永远不应该依赖任何东西。做任何其他事情都会违背封装,阻止你将你的实现换成其他不封装的实现使用 List 而不是仅使用 T[],等等。

编辑:

像你提到的向下转换基本上违反了 Liskov Substition Principle , 获取所有技术和资料。

关于c# - 从接口(interface)转换为底层类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4056013/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com