代码没有采用特定方法

时间:2018-06-15 10:23:10

标签: c#

我有一些奇怪的行为,我在特定地方的代码没有采用特定的方法。没有错误,没有任何错误。它只是在没有踏入它的情况下到达生产线。我正在调试并踩到每个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}}方法。它只是突出显示这行代码并且接下来但不在内部。没有错误,没有什么......为什么会发生?

2 个答案:

答案 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;
}