更流利的C#/ .NET

and*_*eer 15 c#

我的一位同事想出了这个,我想知道别人怎么想?就个人而言,我觉得它很有趣,但想知道它是否太大了?代码示例如下.底部的扩展方法.

请一般的想法.可以添加的其他扩展方法?

var ddl = Page.FindControl("LocationDropDownList") as DropDownList;

ddl.Visible = true;
ddl.SelectedValue = "123";

if(isAdmin)
    ddl  .SelectedValue = "111";
Run Code Online (Sandbox Code Playgroud)

变为:

Page.FindControl("LocationDropDownList")
    .CastAs<DropDownList>()
    .With(d => d.Visible = true)
    .With(d => d.SelectedValue = "123")
    .WithIf(isAdmin, d => d.Items.Add(new ListItem("Admin", "1")));
Run Code Online (Sandbox Code Playgroud)

要么:

 Page.FindControl("LocationDropDownList")
       .CastAs<DropDownList>()
       .With(d =>
       {
           d.Visible = true;
           d.SelectedValue = "123";
       })
       .WithIf(isAdmin, d => d.SelectedValue = "111");
Run Code Online (Sandbox Code Playgroud)

扩展方法:

public static TResult CastAs<TResult>(this object obj) where TResult : class
{
    return obj as TResult;
}

public static T With<T>(this T t, Action<T> action)
{
    if (action == null)
        throw new ArgumentNullException("action");

    action(t);

    return t;
}

public static T WithIf<T>(this T t, bool condition, Action<T> action)
{
    if (action == null)
        throw new ArgumentNullException("action");

    if (condition)
        action(t);

    return t;
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 60

我编写清晰代码的经验法则是:将所有副作用放在语句中; 非语句表达式应该没有副作用.

您的第一个程序版本明确遵循此规则.第二个版本显然违反了它.

另外一个想法:如果我要阅读代码,就像你显示的代码一样,我自然会认为代码的目的是构建一个代表那些操作的延迟评估结构 - 这正是查询理解的原因所在. C#3就是以这种方式构建的.查询表达式的结果是表示查询的延迟应用程序的对象.

如果您的目的是捕捉"在我选择的后期以延迟的方式执行这些副作用"的概念,那么这是一种明智的方法.基本上你正在建立的是一个副作用的monad.如果您的意图仅仅是为急切执行的代码提供不同的语法,那么这只会令人困惑,冗长和不必要.

  • 我认为List.ForEach()不是一个好主意.如何"list.ForEach(foo => {bar(foo);}"比"foreach(列表中的var foo){bar(foo);}"更有价值 - 它是不同顺序的相同字符!通过使ForEach成为一种表达,没有令人信服的代表性力量. (10认同)
  • 像这样的恕我直言的案例的另一个指导原则是:**每个设计都应该解决问题**.目前还不清楚这里的流畅API实际上试图解决什么问题. (3认同)
  • 在什么声明?lambdas里面的语句表达式?当我读到时,我读到"这个方法正在捕获一个副作用操作,然后可以在方法选择的任何时候保存并重新应用." 这与*语句*完全不同,*语句*你知道执行*一次*,而不是零,一,二或一千次.并且你知道它在控制到达程序中的那个点时执行,而不是在某个其他方法选择的其他时间执行. (3认同)
  • 但是,怎么样`list.ForEach(bar)`? (3认同)

mqp*_*mqp 49

除了让读者感到困惑之外,我认为没有任何好处.关于我的回答者,我想知道哪个星球更具可读性.据我所知,第一个版本具有或多或少的完美可读性,而这是相当可读的,但让读者想知道是否有一些奇怪的魔法发生在内部WithWithIf.

与第一个版本相比,它更长,更难打字,更不明显,性能更低.

  • +1,绝对没有收获,现在无论谁阅读代码都必须查找`WithIf`(顺便说一句名字)和朋友来理解它. (9认同)
  • "非常明显"的解决方案是原始解决方案.其他一切都是不必要的,只不过是为了证明你能做什么而制定的编码技巧.无论你叫它什么名字,这种东西都令人难以置信地as as..任何其他名称的玫瑰......或者在这种情况下......任何其他名称的粪便. (8认同)
  • 我喜欢流利的方法.它更容易阅读.它很优雅. (5认同)

Dol*_*hin 11

我想我没看到新版本能给你带来什么.原件非常清晰,不那么罗嗦.我猜它会更快.除非有明显的好处,否则我会避免使用(滥用?)这样的语言功能.


Jul*_*iet 9

再投票"没用".With除了使用方法包装序列语句之外,扩展方法不会执行任何操作.C#已经有一个用于测序语句的内置函数,它被称为;.

类似地,WithIf包装if语句而不对控制流进行任何修改.从我的角度来看,你只是邀请自己采用以下方法:

public static T For<T>(
    this T t, int start, Func<int, bool> cond, Action<T, int> f)
{
    for(int i = start; cond(i); i++)
    {
        f(t, i);
    }
    return t;
}
Run Code Online (Sandbox Code Playgroud)


Jee*_*Bee 6

原件更具可读性.

最简单的API更改是使FindControl()返回的对象成为一个Builder-esque的东西(其中所有set方法都返回'this'):

Page.FindControl("LocationDropDownList")
    .setVisible(true)
    .setSelectedValue(isAdmin ? "111" : "123");
Run Code Online (Sandbox Code Playgroud)


Pie*_*ten 5

如果我见过的话,那是一些扩展方法滥用!


Mat*_*ato 5

这是一个有趣的扩展使用,我很欣赏它的优点.我不确定我是否会使用它,但如果你的团队喜欢它,那么无论如何都要使用它.