我有一些奇怪的行为,我在特定地方的代码没有采用特定的方法。没有错误,没有任何错误。它只是在没有踏入它的情况下到达生产线。我正在调试并踩到每个tep来发现这个问题。我不知道发生了什么,这是我第一次遇到这样的问题。下面找到我的代码,并在最后解释它发生的确切位置。
static class Program
{
private static UnityContainer container;
[STAThread]
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Bootstrap();
Application.Run(container.Resolve<FrmLogin>());
}
private static void Bootstrap()
{
container = new UnityContainer();
container.RegisterType<IRepositoryDal<User>, UserRepositoryDal>();
container.RegisterType<IRepositoryDal<Order>, OrderRepositoryDal>();
container.RegisterType<IDbManager, DbManager>(new InjectionConstructor("sqlserver"));
container.RegisterType<IGenericBal<User>, UserBal>();
container.RegisterType<IGenericBal<Order>, OrderBal>();
}
}
public partial class FrmLogin : Form
{
private readonly IGenericBal<User> _userBal;
public FrmLogin(IGenericBal<User> userBal)
{
InitializeComponent();
_userBal = userBal;
}
private void btnSearch_Click(object sender, EventArgs e)
{
try
{
var a = _userBal.SearchByName("John");
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
public class UserBal : IGenericBal<User>
{
private readonly IRepositoryDal<User> _userRepositoryDal;
public UserBal(IRepositoryDal<User> userRepositoryDal)
{
_userRepositoryDal = userRepositoryDal ?? throw new ArgumentNullException(nameof(userRepositoryDal));
}
public IEnumerable<User> SearchByName(string name)
{
return _userRepositoryDal.SearchByName(name);
}
}
public interface IGenericBal<out T> where T : IEntity
{
IEnumerable<T> SearchByName(string name);
}
public class UserRepositoryDal: IRepositoryDal<User>
{
private readonly IDbManager _dbManager;
public UserRepositoryDal(IDbManager dbManager)
{
_dbManager = dbManager;
}
public IEnumerable<User> SearchByName(string username)
{
var parameters = new List<IDbDataParameter>
{
_dbManager.CreateParameter("@Name", 50, username, DbType.String),
};
username = "JUSTyou";
var userDataTable = _dbManager.GetDataTable("SELECT * FROM T_Marke WHERE Name=@Name", CommandType.Text, parameters.ToArray());
foreach (DataRow dr in userDataTable.Rows)
{
var user = new User
{
Id = int.Parse(dr["Id"].ToString()),
Firstname = dr["Name"].ToString(),
};
yield return user;
}
}
}
public interface IRepositoryDal<T> where T : IEntity
{
IEnumerable<T> SearchByName(string username);
T SearchById(string id);
void Update(T entity);
void Remove(T entity);
void Add(T entity);
}
这里会发生什么:
当我开始使用断点进行调试时,我开始单击按钮,这会在我的代码中找到btnSearch_Click
处理程序。当它发生时,它转到:var a = _userBal.SearchByName("John");
然后转到UserBal
的代码SearchByName
方法。当它达到:return _userRepositoryDal.SearchByName(name);
时,它不会进入UserRepositoryDal
的{{1}}方法。它只是突出显示这行代码并且接下来但不在内部。没有错误,没有什么......为什么会发生?
答案 0 :(得分:4)
这称为&#34;懒惰评估&#34;:https://blogs.msdn.microsoft.com/pedram/2007/06/02/lazy-evaluation-in-c/
简而言之,您使用yield return
返回方法的结果,这意味着代码不会立即得到评估,但实际的方法执行会被推迟到您实际使用某些结果为止评估。
<强>更新强>
如果您想立即评估您的代码,您需要以某种方式使用它。最简单的方法是返回整个结果集以从中创建新的数组或列表。例如,你可以通过替换:
来实现return _userRepositoryDal.SearchByName(name);
使用:
return _userRepositoryDal.SearchByName(name).ToList();
虽然这可能对调试有好处,但它也会消除使用延迟评估所获得的性能提升。
答案 1 :(得分:2)
这段代码是Lazy Enumeration:
public IEnumerable<User> SearchByName(string username)
{
var parameters = new List<IDbDataParameter>
{
_dbManager.CreateParameter("@Name", 50, username, DbType.String),
};
username = "JUSTyou";
var userDataTable = _dbManager.GetDataTable("SELECT * FROM T_Marke WHERE Name=@Name", CommandType.Text, parameters.ToArray());
foreach (DataRow dr in userDataTable.Rows)
{
var user = new User
{
Id = int.Parse(dr["Id"].ToString()),
Firstname = dr["Name"].ToString(),
};
yield return user;
}
}
使用yield return user;
告诉.Net仅在枚举时运行此代码。您在任何时候都无法访问SearchByName
的结果。所以它不会进入它:
public IEnumerable<User> SearchByName(string name)
{
//this doesn't access the result
return _userRepositoryDal.SearchByName(name);
//this would
//return _userRepositoryDal.SearchByName(name).ToList();
}
最简单的方法来修复&#34;这是为了删除枚举,因为我不认为这是你想要的:
public IEnumerable<User> SearchByName(string username)
{
List<User> response = new List<User>();
var parameters = new List<IDbDataParameter>
{
_dbManager.CreateParameter("@Name", 50, username, DbType.String),
};
username = "JUSTyou";
var userDataTable = _dbManager.GetDataTable("SELECT * FROM T_Marke WHERE Name=@Name", CommandType.Text, parameters.ToArray());
foreach (DataRow dr in userDataTable.Rows)
{
var user = new User
{
Id = int.Parse(dr["Id"].ToString()),
Firstname = dr["Name"].ToString(),
};
//Add to a collection
response.Add(user);
}
//return result
return response;
}