2

There are a lot of questions out there that have this error, but that's because it seems like a common error that occurs with lambdas in many scenarios; however, I can't pin down the reason for my issue.

I'm using Lazy and this works fine:

/// <summary>
/// Build a client from the provided data entity.
/// </summary>
/// <param name="fromDataEntity">The data entity from which the client will be built.</param>
/// <returns>The data entity that is built.</returns>
private static Client BuildClient(ClientDataEntity fromDataEntity)
{
    var client = new Client()
    {
        ClientCode = fromDataEntity.ClientCode,
        Name = fromDataEntity.Name,
        BillingAttorneyLazy = new Lazy<Employee>(() => EmployeeLoading.LoadEmployee(fromDataEntity.BillingAttorneyEmployeeUno))
    };

    return client;
}

Here's EmployeeLoading.LoadEmployee just for reference:

/// <summary>
/// Load the employee, if it exists, with the provided employee uno.
/// </summary>
/// <param name="withEmployeeUno">The employee uno for the employee that will be loaded.</param>
/// <returns>The employee that is loaded, if one exists for the provided uno, or else null.</returns>
internal static Employee LoadEmployee(uint withEmployeeUno)
{
    var entity = CmsDataAbstraction.GetEmployeeDataEntity(withEmployeeUno);
    return (entity != null) ? BuildEmployee(entity) : null;
}

Now, when I do something similar:

/// <summary>
/// Build and return an employee from the provided data entity.
/// </summary>
/// <param name="fromDataEntity">The data entity from which the employee will be built.</param>
/// <returns>Build and return an employee from the provided data entity.</returns>
private static Employee BuildEmployee(EmployeeDataEntity fromDataEntity)
{
    var employee = new Employee()
    {
        EmployeeCode = fromDataEntity.Code,
        WorksiteUserNameLazy = new Lazy<string>(() => GetEmployeeWorksiteUserName(employee))
    };

    return employee;
}

I'm getting an error on the lambda () => GetEmployeeWorksiteUserName(employee):

Cannot convert lambda expression to type 'bool' because it is not a delegate type

Here is GetEmployeeWorksiteUserName for reference:

/// <summary>
/// Retrieve the Worksite username for the provided employee.
/// </summary>
/// <param name="forEmployee">The employee whose Worksite username will be retrieved.</param>
/// <returns>The Worksite username for the associated employee.</returns>
private static string GetEmployeeWorksiteUserName(Employee forEmployee)
{
    var authorADAccountName = FirmInformationDataAbstraction.GetEmployeeActiveDirectoryUsername(forEmployee.EmployeeCode);

    if (WorksiteDataAbstraction.UserExists(authorADAccountName))
    {
        return authorADAccountName;
    }
    else // user doesn't exist in Worksite.
    {
        return string.Empty;
    }
}

I believe the compiler thinks I'm trying to call the constructor for Lazy<T> which takes a single bool, but it's well-documented that my approach should work (see sites like this, e.g.).

Why is this approach working fine in the first case and getting the error in the second case? How do I fix it?

rory.ap
  • 34,009
  • 10
  • 83
  • 174
  • What is the type of `WorksiteUserNameLazy`? – haim770 Jun 15 '16 at 12:30
  • I guess you could try to force the issue and use the constructor that takes a delegate and a bool `new Lazy(() => GetEmployeeWorksiteUserName(employee), true)` – juharr Jun 15 '16 at 12:33
  • @juharr -- Thanks, that covers the "how to fix it" part. I'm still curious as to why it's occurring. – rory.ap Jun 15 '16 at 12:36
  • So I just tried to recreate this and got an error about using the variable I was creating in the lambda "Cannot use local variable before it is declared". – juharr Jun 15 '16 at 12:38
  • Odd. I'm in the midst of a refactoring and ironing out other compiler errors. I've found VS (2013 at least) isn't always forthcoming with the total number of errors, i.e. you have to fix one to reveal others. Maybe that's what's going on here. – rory.ap Jun 15 '16 at 12:40
  • I suspect the inference failure is hiding an error, which is probably caused by you trying to reference the `employee` variable within the expression that defines it. It should work if you remove the object initialiser and use a sequence of property assignments. – Lee Jun 15 '16 at 12:40
  • I'm using VS 2015, so maybe it's just an issue with the older compiler. – juharr Jun 15 '16 at 12:43
  • @Lee -- That was it. It would be nice if that error took precedence over the misleading error that did appear. – rory.ap Jun 15 '16 at 12:43
  • Anyway, thanks all for your help. – rory.ap Jun 15 '16 at 12:48

2 Answers2

2

It's because you're using the employee before it's been declared (effectively in the constructor).

Note the difference:

var employee = new Employee()
{
    EmployeeCode = fromDataEntity.Code
};
employee.WorksiteUserNameLazy = 
    new Lazy<string>(() => GetEmployeeWorksiteUserName(employee));
iggymoran
  • 4,059
  • 2
  • 21
  • 26
2

I have tried to reproduce your issue, but I'm getting compiler errors because I'm not able to use the employee reference before it's declared. Can you try to do it this way to check if it solves your issue?

/// <summary>
/// Build and return an employee from the provided data entity.
/// </summary>
/// <param name="fromDataEntity">The data entity from which the employee will be built.</param>
/// <returns>Build and return an employee from the provided data entity.</returns>
private static Employee BuildEmployee(EmployeeDataEntity fromDataEntity)
{
    var employee = new Employee()
    {
        EmployeeCode = fromDataEntity.Code            
    };
    employee.WorksiteUserNameLazy = new Lazy<string>(() => GetEmployeeWorksiteUserName(employee));
    return employee;
}