隐含上下文相关运算符的想法。 (点)作为语法糖

时间:2011-03-10 07:55:54

标签: c# syntax

与其他语言相比,C#中的某些操作似乎不必要地笨重。例如lambdas:

students.GroupBy(student => student.State).Where(student => student.Count > 1).OrderByReversed(studentGroup => studentGroup.Count);

这可以通过使用非常短的变量名来缩短:

students.GroupBy(s => s.State).Where(s => s.Count > 1).OrderByReversed(sg => sg.Count);

但是这样变量在上下文之外很难理解。进一步缩短它的一种方法是简单地完全跳过单参数列表,并让点隐含参数:

students.GroupBy(.State).Where(.Count > 1).OrderByReversed(.Count);

对我而言,这比上述任何一个都更具可读性。它仅适用于单参数lambdas,当然它的含义是从上下文推断出来的。

对于lambdas,

编辑,其中参数本身直接使用'。'可以用作直接占位符:

var lines = text.Split("\n").Where(line => line != "");

可以使用以下方法缩短一点:

var lines = text.Split("\n").Where(. != "");

可以使用这种下级运算符的另一个地方是Enum传递。当从上下文中显而易见时,枚举的名称通常会传递得太多。例如,使用OpenTK(OpenGL的C#实现),创建一个简单的纹理需要每次调用这样的东西:

GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, bd.Width, bd.Height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgr, PixelType.UnsignedByte, myPointer);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);

(请注意,OpenTK.Graphics.OpenGL.PixelFormat必须使用全名传递,因为它与System.Drawing.Imaging.PixelFormat冲突;使用点符号不再需要这样做)

这包含许多枚举调用,这些调用在等效的C ++实现中要短得多,因此乍一看更容易阅读。我们可以尝试跳过枚举名称,并从上下文中推断出它们(被调用方法的参数类型):

GL.TexImage2D(.Texture2D, 0, .Rgba, bd.Width, bd.Height, 0, .Bgr, .UnsignedByte, myPointer);
GL.TexParameter(.Texture2D, .TextureMinFilter, (int).Linear);
GL.TexParameter(.Texture2D, .TextureMagFilter, (int).Linear);

这不仅短,而且甚至比C ++更短,易于阅读,同时保留了语言的强类型性质。我确定还有其他地方可以使用,这些只是我希望在未来的C#版本中看到的一些语法示例。您怎么看?这是个好主意吗?

2 个答案:

答案 0 :(得分:1)

关于你的第一个例子,假设我们看到了

(x,y) => .z + .q;

zx还是y的成员?如果xy都有一个名为z的成员?

,该怎么办?

答案 1 :(得分:1)

不确定这是多少问题,但我会试着把我的两分钱放进去。

我从VB中遗漏的一个功能是[With][1]语句。它肯定会导致可怕的混乱(想象一下嵌套With会做什么)但它确实保存了一些键击,并且使代码更直观(在某种程度上“这是我设置属性的地方)的SqlConnection对象“)。然后是C#3中的Object Inicializers,一个类似(设计得更好)的功能,它们通常足以满足大多数With场景。

C#团队非常出色地让开发人员专注于what而不是how,从而消除了各地的多余语法。 “lambda”存在于C#2中,只有它们被称为匿名委托,它们的语法类似于:

itemTypes.Find(delegate(ItemType itemType) { return itemType.Name == typeName; });

在c#3中缩短为

itemTypes.Find(itemType => itemType.Name == typeName);

这只是简化语法的一个例子,使用起来更容易,更明显,并提高了功能的可见性。我不知道很多开发人员使用过,甚至不知道如何使用匿名代表,但是现在,任何值得他认识的C#开发人员都应该对lambdas感到满意。

现在,看看你提出的功能,让我们来衡量一下优点和缺点(从开发人员的角度来看,而不是从语言设计的角度来看):

亲:

  • 语法不足
  • 在大多数使用场景中提高易用性
  • 隐含增益=>更容易在C#
  • 的黑暗艺术中训练新门徒

Con(lambdas):

  • 两个或多个参数方法中的混淆(这可以通过两个参数方法使其成为非法来解决)
  • 嵌套lambda中的混乱(这与嵌套with的问题相同 - 这只是一种不好的做法)

Con(Enums):

  • 枚举不是真正的强类型,所以在某些情况下这可能会爆炸(这只是一种感觉,没有一个例子)

最重要的是,我想在lambdas的情况下看到这个功能,但在枚举的情况下感觉有点不确定。

Bottomer line,我不认为这个功能有一个真正的好处来证明语法的改变,所以它可能不会很快实现(如果有的话)。元组和扩展属性仍然是我最喜欢的C#的非存在特性。