【问题标题】:List is still passed by reference after using new List<T>(list)使用 new List<T>(list) 后,List 仍然通过引用传递
【发布时间】:2013-11-11 14:39:37
【问题描述】:

在我的控制器中,我从 CSV 中读取用户,如下所示:

var users = Utilities.GetUsersFromCSV(path, userType, course);

这会读取一个 CSV 文件并用它构造 User 对象。一个可能相关的部分是密码的创建:

public static List<User> GetUsersFromCSV(string filepath, string userType, Course course) {
    var users = new List<User>();
    var user = new User();
    GeneratePassword(ref user);
    return users;
}

private static void GeneratePassword(ref User user) {
    var size = Rand.Value.Next(0, 3) + 8;
    var sb = new StringBuilder();

    var shuffledlist = Chars.OrderBy(a => Guid.NewGuid()).ToList();

    for (var i = 0; i < size; i++) {
          sb.Append((char) shuffledlist[i]);
    }

    user.Password = sb.ToString();
}

从 CSV 文件创建用户后,我想将它们添加到数据库中,如下所示:

_userRepository.AddUsers(Utilities.HashPasswords(users));

哪些调用

public static List<User> HashPasswords(List<User> users) {
   var newList = new List<User>(users);
   foreach (var user in newList) {
        user.Password = CalculateSha1Hash(user.Password, user.Login);
   }

   return newList;
}

根据this 的回答,正在传输到存储库的用户列表现在应该包含散列密码,而我的控制器中的users 列表应该仍然包含原始密码。但是在调试过程中,我注意到HashPasswords 也会影响users 中的密码。

这是什么原因造成的?

【问题讨论】:

  • 这是正确的,因为对于引用类型,引用的副本将传递给您的方法。但是这个参考仍然指向相同的数据。如果您想避免这种情况,您必须创建对象的副本并传递此副本。这在您发布的链接中也有说明:'如果您想复制列表本身,List 有一个方便的构造函数,它需要一个 IEnumerable。 '。
  • 您的代码无法编译。方法 GetUsersFromCSV 不返回值。
  • @user1567896:这不是var newList = new List&lt;User&gt;(users); 所做的吗? @helb:显然我遗漏了大部分代码,一切都可以编译。为了清楚起见,我将对其进行编辑。
  • 我不认为该列表是通过引用解析的.. 但列表中的Users 可能是!
  • @OP:正如 Rob 已经回答的那样。您需要创建一个深层副本。 (将对象的所有实习生值复制到“新”对象)

标签: c# pass-by-reference


【解决方案1】:

newList 对象是浅拷贝。我会在原始列表中使用 Linq Select 来创建深层副本。

newList = users.Select(u => CopyAndChangePassword(u));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-27
    • 2016-01-30
    • 1970-01-01
    • 2018-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多