【问题标题】:Using delegates, anonymous(lambda) functions, and function pointers使用委托、匿名 (lambda) 函数和函数指针
【发布时间】:2013-08-09 23:19:39
【问题描述】:

我已经阅读了一些关于匿名 (lambda) 函数和委托的内容。我相信我正在处理我的部分功能可以/应该使用它们的情况。我不确定我的假设是否正确。

当前代码:

fDoSave(fGetSqlCheckEmpJob(), fGetSqlUpdateEmpJob(), fGetSqlInsertEmpJob());
fDoSave(fGetSqlCheckEmpPayrl(), fGetSqlUpdateEmpPayrl(), fGetSqlInsertEmpPayrl());
fDoSave(fGetSqlCheckEEO(), fGetSqlUpdateEEO(), fGetSqlInsertEEO());
fDoSave(fGetSqlCheckEmpPhone(), fGetSqlUpdateEmpPhone(), fGetSqlInsertEmpPhone());

fGetSqlCheck...() - 将 sql 语句作为字符串返回,该字符串返回具有特定 ID 的所有行的 count() fGetSqlUpdate...() 将 sql 语句作为执行更新的字符串返回。 fGetSqlInsert...() 将 sql 语句作为执行插入的字符串返回。 fDoSave() 根据fGetCheck...() 返回的值进行更新或插入

fGetSql 函数如下所示:

private string fGetSql...()
{
   StringBuilder sb = new StringBuilder();
   //Create sql statement
   return sb.ToString();
}

fDoSave 函数如下所示:

private void fDoSave(string sSql_Check, string sSql_Update, sSql_Insert)
{
   OracleDataReader dr = ERPDB.sqlGetDataReader(sSql_Check);
   while (dr.Read())
   {
        if(fCheckIfRecrodExists(dr) > 0) //if fGetSqlCheck...() found a row with a specific ID
            //do update using sSql_Update
        else
            //do insert using sSql_Insert
    }
}

这可以使用 lambda 函数或委托重写吗?应该吗?应该怎么改写?

【问题讨论】:

  • 这些方法都是什么?
  • 如果您对某个问题投了反对票,那么解释一下您认为应该更改问题的原因和方式将是一种礼貌(并且非常有帮助)。
  • 我不能,因为你的问题对我没有任何意义。
  • 我们需要了解每种方法的作用,以便做出任何判断。因为代码并不清楚它的作用。如果那是你的代码,你也可以考虑改变你的编码风格。
  • @I4V “这可以使用 lambda 函数或委托重写吗?应该如何重写?”你觉得难以理解吗?

标签: c# lambda delegates anonymous-function


【解决方案1】:

你的问题还是含糊的,不过我还是这么说吧。

案例:

1:可重用和“静态”
如果您重用 SQL 语句并且它们有些静态,请将它们放在属性中。并考虑更好的名字。

2:可重复使用,但“变量”虽然简单
如果你重用 SQL 语句并且它们是可变的但不占用太多 CPU,这意味着它们会随着不同的状态而变化,并且创建和构建的速度非常快,那么就让它保持原样吧。

3:可重用但“可变”且复杂
如果您重用 SQL 语句并且它们是可变的但非常复杂并且需要大量 CPU 能力,请将它们放在方法中,但将它们作为委托调用,不要让它们匿名。

4:不可重用但“可变”且复杂
如果您永远不会重用 SQL 语句(可能永远不会如此)并且它们是可变的且非常复杂并且需要大量 CPU 能力,请将它们放在匿名函数中。

在所有情况下
使用更好的名称。

我的建议
我更喜欢案例 1 和 2,因为其余的似乎是对可能不存在的问题的过于复杂的解决方案。
另外,我不知道你的整个代码库,但我不喜欢应该保存的对象没有提供给 fDoSave()。

我会这样做:

// Also often called Upsert short for "Update or Insert"
public int Save(EmpObj employeeObj) 
{
     if(CheckIfEmployeeExists(employeeObj))
     {
         return Update(employeeObj); // returns rows affected
     }
     else
     {
         return Insert(employeeObj); // Returns new Id of the employee.
     }
}

// Other methods, where the select, update and insert statements lies 
or gets called    and build
public bool CheckIfEmployeeExists(employeeObj) // Check If Employee Exists
public int Update(employeeObj); // Updates the employee
public int Insert(employeeObj); // Inserts the employee

【讨论】:

  • 感谢您抽出宝贵时间回答并提供建设性的 cmets。关于命名约定。我的公司有一个我必须遵守的命名约定。另外,我认为 fGetSqlInsertEmpPayrl 非常具有描述性。 'f' 表示函数,'GetSql' 表示它将返回一个 sql 语句,'I​​nsert' 因为它将是一个插入语句,'EmpPayrl' 因为那是它在其上运行的表。请让我知道什么是更好的/你的方法。
  • 更新答案后,我了解您对代码的不满意之处。我不能这样做,因为它不是我的代码,它是大型旧代码库的一部分。项目要求的一部分是尽量减少代码更改。 :) 您回答的第二部分是一个很好的建议,但与我的问题无关。我没有问“如何像不是 1996 年那样重写我的代码”:)
  • 首先我不喜欢匈牙利风格,但这比什么都宗教,除了 GetSql... 看起来像 java getter,这可能表明你没有充分使用 C#潜在的。最后,我不完全确定您的代码做了什么,以及为什么这样做。 fDoSave,为什么需要 3 个 SQL 语句?直到你进一步解释我才知道,但这是一个结构问题而不是命名约定问题。
  • @Azzi 当然,我有点期待你的回复,这也是为什么它只是一个建议,与你原来的问题没有真正的背景。
  • @Azzi 太好了,我想是的,您仍然可以使用属性,但是在类别 1 和 2 中,您可以根据不同的场景选择您想要的任何一个,但使用方法而不是属性(这可以解决同样的问题)对于变量语句,方法告诉未来的开发者,它是一个比一个预设值更复杂的过程。 - 我也很高兴能帮上忙 :)