With block equivalent in C#?
我知道vb.net,正在尝试更新我的C。C中是否有一个与块等效的?
谢谢
虽然C没有任何与一般情况直接等效的方法,但C 3获得了构造函数调用的对象初始值设定项语法:
1 |
更多详细信息,请参阅C第8章-您可以从曼宁的网站免费下载。
(免责声明-是的,让更多的人掌握这本书符合我的利益。但是,嘿,这是一个免费的章节,它提供了关于相关主题的更多信息…)
这就是Visual C程序管理器必须说的:为什么C没有"with"声明?
Many people, including the C# language designers, believe that 'with'
often harms readability, and is more of a curse than a blessing. It is
clearer to declare a local variable with a meaningful name, and use
that variable to perform multiple operations on a single object, than
it is to have a block with a sort of implicit context.
正如上面链接的Visual C程序管理器所说,在某些有限的情况下,WITH语句更有效,他给出的例子是,当它被用作一个速记来重复访问复杂表达式时。
通过使用扩展方法和泛型,您可以通过添加如下内容,创建类似于WITH语句的内容:
1 2 3 4 5 | public static T With<T>(this T item, Action<T> action) { action(item); return item; } |
举一个简单的例子,说明如何使用lambda语法,然后可以使用它来更改如下内容:
1 2 | updateRoleFamily.RoleFamilyDescription = roleFamilyDescription; updateRoleFamily.RoleFamilyCode = roleFamilyCode; |
对此:
1 2 3 4 5 | updateRoleFamily.With(rf => { rf.RoleFamilyDescription = roleFamilyDescription; rf.RoleFamilyCode = roleFamilyCode; }); |
在这样一个例子中,唯一的优势可能是更好的布局,但是有了一个更复杂的引用和更多的属性,它可以给您提供更可读的代码。
不,没有。
在"使用对象"部分的页面下方约3/4处:
VB:
1 2 3 4 | With hero .Name ="SpamMan" .PowerLevel = 3 End With |
C:
1 2 3 | //No"With" construct hero.Name ="SpamMan"; hero.PowerLevel = 3; |
您可以使用参数累加器模式。
关于这一点的大讨论如下:
http://blogs.msdn.com/csharpfaq/archive/2004/03/11/87817.aspx
我要做的是使用csharp-ref关键字。例如:
1 | ref MySubClassType e = ref MyMainClass.MySubClass; |
然后您可以使用如下快捷方式:用
最简单的语法是:
1 2 3 4 5 6 7 8 9 10 11 |
实际上,如果您想重新使用变量名,这样的额外代码块非常方便。
这里是江户十一〔0〕的大粉丝!
这是我目前的C代码:
1 2 3 4 5 | if (SKYLib.AccountsPayable.Client.ApiAuthorization.Authorization.AccessTokenExpiry == null || SKYLib.AccountsPayable.Client.ApiAuthorization.Authorization.AccessTokenExpiry < DateTime.Now) { SKYLib.AccountsPayable.Client.ApiAuthorization.Authorization.Refresh(); _api = new SKYLib.AccountsPayable.Api.DefaultApi(new SKYLib.AccountsPayable.Client.Configuration { DefaultHeader = SKYLib.AccountsPayable.Client.ApiAuthorization.Authorization.ApiHeader }); } |
在VB中,它可以是:
1 2 3 4 |
我想更清楚了。您甚至可以通过调整
顺便说一下,这种情况并不常见,但我有时会用到:
而不是
1 2 3 4 5 6 7 |
你可以使用
1 2 3 4 5 |
你要冒着打手腕的危险-我也是!-但似乎你得到了
注意:这可能偶尔会出错,所以只能用于非关键代码。或者根本没有。记住:你有选择…
我用这种方式:
1 2 3 4 5 6 7 8 9 | worksheet.get_Range(11, 1, 11, 41) .SetHeadFontStyle() .SetHeadFillStyle(45) .SetBorders( XlBorderWeight.xlMedium , XlBorderWeight.xlThick , XlBorderWeight.xlMedium , XlBorderWeight.xlThick) ; |
setHeadFontStyle/setHeadFillStyle是如下范围的extMethod:
1 2 3 4 5 | public static Range SetHeadFillStyle(this Range rng, int colorIndex) { //do some operation return rng; } |
执行一些操作并返回下一个操作的范围
它看起来像Linq:)
但现在仍然不能完全像它--属性设定值
1 2 3 4 | with cell.Border(xlEdgeTop) .LineStyle = xlContinuous .Weight = xlMedium .ColorIndex = xlAutomatic |
有时,您可以通过执行以下操作来摆脱困境:
1 2 3 4 5 | var fill = cell.Style.Fill; fill.PatternType = ExcelFillStyle.Solid; fill.BackgroundColor.SetColor(Color.Gray); fill.PatternColor = Color.Black; fill.Gradient = ... |
(epplus@http://zeeshanumardotnet.blogspot.com的代码示例)
我认为"with"的壁橱是
1 2 3 4 5 6 | using static System.Math; ... public double Area { get { return PI * Pow(Radius, 2); } // PI == System.Math.PI } |
更多信息:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-static
还有一个有趣的with模式实现
1 2 | public static T With<T>(this T o, params object[] pattern) => o; public static T To<T>(this T o, out T x) => x = o; |
您可以通过链接浏览更多详细信息并研究在线代码示例。
使用的变化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | static Point Sample0() => new Point().To(out var p).With( p.X = 123, p.Y = 321, p.Name ="abc" ); public static Point GetPoint() => new Point { Name ="Point Name" }; static string NameProperty { get; set; } static string NameField; static void Sample1() { string nameLocal; GetPoint().To(out var p).With( p.X = 123, p.Y = 321, p.Name.To(out var name), /* right side assignment to the new variable */ p.Name.To(out nameLocal), /* right side assignment to the declared var */ NameField = p.Name, /* left side assignment to the declared variable */ NameProperty = p.Name /* left side assignment to the property */ ); Console.WriteLine(name); Console.WriteLine(nameLocal); Console.WriteLine(NameField); Console.WriteLine(NameProperty); } static void Sample2() /* non-null propogation sample */ { ((Point)null).To(out var p)?.With( p.X = 123, p.Y = 321, p.Name.To(out var name) ); Console.WriteLine("No exception"); } static void Sample3() /* recursion */ { GetPerson().To(out var p).With( p.Name.To(out var name), p.Subperson.To(out var p0).With( p0.Name.To(out var subpersonName0) ), p.GetSubperson().To(out var p1).With( /* method return */ p1.Name.To(out var subpersonName1) ) ); Console.WriteLine(subpersonName0); Console.WriteLine(subpersonName1); } |
如果使用结构[值类型],类似的扩展方法也会很有用。
1 | public static TR Let<T, TR>(this T o, TR y) => y; |
可能在With方法之后应用,因为默认情况下将返回未修改的结构副本
1 2 3 4 5 6 7 8 9 10 11 12 | struct Point { public double X; public double Y; public string Name; } static Point Sample0() => new Point().To(out var p).With( p.X = 123, p.Y = 321, p.Name ="abc" ).Let(p); |
喜欢的话就尽情享受吧!
如果有多个级别的对象,可以使用"using"指令获得类似的功能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | using System; using GenderType = Hero.GenderType; //This is the shorthand using directive public partial class Test : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { var myHero = new Hero(); myHero.Name ="SpamMan"; myHero.PowerLevel = 3; myHero.Gender = GenderType.Male; //instead of myHero.Gender = Hero.GenderType.Male; } } public class Hero { public enum GenderType { Male, Female, Other } public string Name; public int PowerLevel; public GenderType Gender; } |
嗯,我从来没有在任何深度上使用过vb.net,所以我在这里做了一个假设,但我认为"使用"块可能接近你想要的。
使用定义变量的块范围,请参见下面的示例
1 2 3 4 5 | using ( int temp = someFunction(param1) ) { temp++; // this works fine } temp++; // this blows up as temp is out of scope here and has been disposed |
这是微软的一篇文章,它解释了更多
编辑:是的,这个答案是错误的-最初的假设是错误的。vb的"with"更像是新的c对象初始化器:
1 |