为什么我不能在匿名方法中声明一个与变量同名的变量
Why can I not declare a variable with the same name as a variable in an anonymous method
我正在创建一种方法,将默认用户加载到 MVC5 模板附带的身份数据库中。我最终遇到了编译错误(请参阅下面的完整代码)
var user = CreateUser("email@email.email",true);
准确的错误是Error 16 A local variable named 'user' cannot be declared in this scope because it would give a different meaning to 'user', which is already used in a 'child' scope to denote something else
我不明白这是怎么回事,我发现同样令人困惑的是,当我注释掉这一行时,下一行找不到变量 user
。如果编译因为之前的声明而拒绝让我使用user
,那么在删除重复声明后如何找不到user
。
我认为这与保留名称的 closure/inline 方法有关,但我不确定。我也知道我可以通过更改变量名来解决这个问题,我对原因更感兴趣。
这是我目前正在编写的方法的一个简化示例:
internal static void CreateDefaultUsers(IdentityDb context)
{
var defaultPassword = "admin";
var userManager = new UserManager<User>(new UserStore<User>(context));
var roleManager = new RoleManager<UserRole>(new RoleStore<UserRole>(context));
Func<string, User> CreateUser = (string email) =>
{
User user = context.Users.SingleOrDefault(u => u.UserName == email);
if (user == null)
{
user = new EziOrderUser {
FirstName = email.Substring(0, email.LastIndexOf("@")),
Email = email, UserName = email, EmailConfirmed = true };
userManager.Create(user, defaultPassword);
userManager.AddToRole(user.Id, "User");
}
return user;
};
var user = CreateUser("email@email.email"); // <-- Error here
userManager.AddToRole(user.Id, "Administrator"); // <-- Then here
}
(没有检查这个示例编译,但是它确实说明了问题)
基本上,这是一项旨在让您的生活更轻松的功能。 :-) 如果你能做到这一点,你就会遇到类型冲突。
{
// scope 1
Func<string, User> CreateUser = (string email) =>
{
// scope 2
User user = context.Users.SingleOrDefault(u => u.UserName == email);
// ...**1
return user;
};
// **2
var user = CreateUser("email@email.email");
userManager.AddToRole(user.Id, "Administrator"); // <-- Then here
在您的示例中,**2 和 **1 的用户类型是什么?假设 CreateUser returns 是一个字符串 - 这将推断在范围 1 中用户可以获得类型 string
和类型 User
。由于范围 2 已关闭,您可以争辩说这是正确使用的范围,但这将使开发人员更难阅读代码。强制每个范围只能使用一个名称会使它更容易。
并非所有语言都有此行为,f.ex。 C++ 允许你做这些事情。 (这可能是他们首先这样做的原因:-)
顺便说一句,重复使用名称是可以的,只要它们不出现在同一范围内即可。例如:
Func<string, User> CreateUser = (string email) =>
{
User user = context.Users.SingleOrDefault(u => u.UserName == email);
// ...
return user;
};
{
// New scope - user is not contained in a shared scope. This is OK.
var user = CreateUser("email@email.email");
userManager.AddToRole(user.Id, "Administrator");
}
我正在创建一种方法,将默认用户加载到 MVC5 模板附带的身份数据库中。我最终遇到了编译错误(请参阅下面的完整代码)
var user = CreateUser("email@email.email",true);
准确的错误是Error 16 A local variable named 'user' cannot be declared in this scope because it would give a different meaning to 'user', which is already used in a 'child' scope to denote something else
我不明白这是怎么回事,我发现同样令人困惑的是,当我注释掉这一行时,下一行找不到变量 user
。如果编译因为之前的声明而拒绝让我使用user
,那么在删除重复声明后如何找不到user
。
我认为这与保留名称的 closure/inline 方法有关,但我不确定。我也知道我可以通过更改变量名来解决这个问题,我对原因更感兴趣。
这是我目前正在编写的方法的一个简化示例:
internal static void CreateDefaultUsers(IdentityDb context)
{
var defaultPassword = "admin";
var userManager = new UserManager<User>(new UserStore<User>(context));
var roleManager = new RoleManager<UserRole>(new RoleStore<UserRole>(context));
Func<string, User> CreateUser = (string email) =>
{
User user = context.Users.SingleOrDefault(u => u.UserName == email);
if (user == null)
{
user = new EziOrderUser {
FirstName = email.Substring(0, email.LastIndexOf("@")),
Email = email, UserName = email, EmailConfirmed = true };
userManager.Create(user, defaultPassword);
userManager.AddToRole(user.Id, "User");
}
return user;
};
var user = CreateUser("email@email.email"); // <-- Error here
userManager.AddToRole(user.Id, "Administrator"); // <-- Then here
}
(没有检查这个示例编译,但是它确实说明了问题)
基本上,这是一项旨在让您的生活更轻松的功能。 :-) 如果你能做到这一点,你就会遇到类型冲突。
{
// scope 1
Func<string, User> CreateUser = (string email) =>
{
// scope 2
User user = context.Users.SingleOrDefault(u => u.UserName == email);
// ...**1
return user;
};
// **2
var user = CreateUser("email@email.email");
userManager.AddToRole(user.Id, "Administrator"); // <-- Then here
在您的示例中,**2 和 **1 的用户类型是什么?假设 CreateUser returns 是一个字符串 - 这将推断在范围 1 中用户可以获得类型 string
和类型 User
。由于范围 2 已关闭,您可以争辩说这是正确使用的范围,但这将使开发人员更难阅读代码。强制每个范围只能使用一个名称会使它更容易。
并非所有语言都有此行为,f.ex。 C++ 允许你做这些事情。 (这可能是他们首先这样做的原因:-)
顺便说一句,重复使用名称是可以的,只要它们不出现在同一范围内即可。例如:
Func<string, User> CreateUser = (string email) =>
{
User user = context.Users.SingleOrDefault(u => u.UserName == email);
// ...
return user;
};
{
// New scope - user is not contained in a shared scope. This is OK.
var user = CreateUser("email@email.email");
userManager.AddToRole(user.Id, "Administrator");
}