我正在创建一个方法来将默认用户加载到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
。
我认为这与持有名称的闭包/内联方法有关,但我不确定。我也知道我可以通过更改变量名来解决这个问题,我对它的原因更感兴趣。
以下是我目前正在编写的方法的简化示例:
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
}
(没有检查过这个样本编译,但确实说明了问题)
答案 0 :(得分:1)
基本上它是一项让您的生活更轻松的功能。 :-)如果你能做到这一点,你可以得到类型冲突。
? f(x) = { (t) -> x + t }
%1 = (x)->(t)->x+t
? g(x) = { local(y); y = f(x); (t) -> y(t) }
%2 = (x)->local(y);y=f(x);(t)->y(t)
? h = g(2)
%3 = (t)->my(x=2);y(t)
? h(1)
*** at top-level: h(1)
*** ^----
*** in function h: y(t)
*** ^----
*** not a function in function call
*** Break loop: type 'break' to go back to GP
在您的示例中,** 2和** 1的用户类型是什么?假设CreateUser返回一个字符串 - 这将推断在范围1中用户可以同时获得类型{
// 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
和类型string
。由于范围2已关闭,您可以认为这是正确使用的,但这将使开发人员更难以阅读代码。强制每个范围只能使用一次名称,这样可以更容易。
并非所有语言都有这种行为,f.ex。 C ++允许你做这些事情。 (这可能是他们首先做到这一点的原因: - )
顺便说一句,重新使用名称是可以的,只要它们不会出现在同一范围内。例如:
User