我知道VB.Net,我正在努力搞清楚我的C#。在C#中是否有一个With块等价物?
谢谢
虽然C#与一般情况没有任何直接等价,但C#3获取构造函数调用的对象初始化语法:
var foo = new Foo { Property1 = value1, Property2 = value2, etc };
有关更多详细信息,请参阅深度C#的第8章 - 您可以从Manning's web site免费下载。
(免责声明 - 是的,将这本书送到更多人的手中符合我的利益。但是,嘿,这是一个免费的章节,为您提供有关相关主题的更多信息......)
我用这种方式:
worksheet.get_Range(11, 1, 11, 41)
.SetHeadFontStyle()
.SetHeadFillStyle(45)
.SetBorders(
XlBorderWeight.xlMedium
, XlBorderWeight.xlThick
, XlBorderWeight.xlMedium
, XlBorderWeight.xlThick)
;
SetHeadFontStyle / SetHeadFillStyle是Range的ExtMethod,如下所示:
public static Range SetHeadFillStyle(this Range rng, int colorIndex)
{
//do some operation
return rng;
}
执行一些操作并返回Range以进行下一步操作
它看起来像Linq :)
但现在仍然不能完全看起来像 - 财产设定值
with cell.Border(xlEdgeTop)
.LineStyle = xlContinuous
.Weight = xlMedium
.ColorIndex = xlAutomatic
这里是With
的忠实粉丝!
这是我目前的C#代码:
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中它可能是:
With SKYLib.AccountsPayable.Client.ApiAuthorization.Authorization
If .AccessTokenExpiry Is Nothing OrElse .AccessTokenExpiry < Now Then .Refresh()
_api = New SKYLib.AccountsPayable.Api.DefaultApi(New SKYLib.AccountsPayable.Client.Configuration With {DefaultHeader = .ApiHeaders}
End With
我觉得更清楚。您甚至可以通过调整With
变量来调整它以使其更简洁。而且,风格方面,我还有一个选择!也许C#项目经理忽略了一些东西。
顺便说一下,看到这个并不常见,但我偶尔会用它:
代替
Using oClient As HttpClient = New HttpClient
With oClient
.BaseAddress = New Uri("http://mysite")
.Timeout = New TimeSpan(123)
.PostAsync( ... )
End With
End Using
您可以使用
With New HttpClient
.BaseAddress = New Uri("http://mysite")
.Timeout = New TimeSpan(123)
.PostAsync( ... )
End With
你冒着手腕拍打的风险 - 就像发布一样! - 但似乎你在处理等方面获得了Using
声明的所有好处,而没有额外的琐事。
注意:偶尔会出错,因此只能将其用于非关键代码。或者完全没有。记住:你有选择......
还有一个有趣的with-pattern实现
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;
您可以通过the link浏览更多细节并研究online code samples。
使用的变化
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);
}
如果使用结构[值类型],类似的扩展方法也很有用
public static TR Let<T, TR>(this T o, TR y) => y;
可以在With方法之后应用,因为默认情况下将返回未修改的struct副本
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);
如果你愿意,享受吧!
我认为“with”的壁橱是static using
,但只适用于静态的方法或属性。例如
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
如果有多个对象级别,您可以使用“using”指令获得类似的功能:
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,所以我在这里做了一个假设,但我认为'使用'块可能接近你想要的。
using定义变量的块范围,请参见下面的示例
using ( int temp = someFunction(param1) ) {
temp++; // this works fine
}
temp++; // this blows up as temp is out of scope here and has been disposed
Here is an article from Microsoft that explains a bit more
编辑:是的,这个答案是错误的 - 最初的假设是不正确的。 VB的'WITH'更像是新的C#对象初始化器:
var yourVariable = new yourObject { param1 = 20, param2 = "some string" };
这就是Visual C#项目经理所说的:Why doesn't C# have a 'with' statement?
很多人,包括C#语言设计师,都认为'with'常常会损害可读性,而且更多的是诅咒而不是祝福。声明具有有意义名称的局部变量更明确,并使用该变量对单个对象执行多个操作,而不是使用具有某种隐式上下文的块。
正如上面链接的Visual C#程序管理器所说,在有些情况下,With语句更有效,这是他用作重复访问复杂表达式的简写时给出的示例。
使用扩展方法和泛型,您可以通过添加如下内容来创建与With语句模糊等价的内容:
public static T With<T>(this T item, Action<T> action)
{
action(item);
return item;
}
举一个如何使用它的简单例子,使用lambda语法然后你可以用它来改变这样的东西:
updateRoleFamily.RoleFamilyDescription = roleFamilyDescription;
updateRoleFamily.RoleFamilyCode = roleFamilyCode;
对此:
updateRoleFamily.With(rf =>
{
rf.RoleFamilyDescription = roleFamilyDescription;
rf.RoleFamilyCode = roleFamilyCode;
});
在这样的示例中,唯一的优势可能是更好的布局,但是使用更复杂的引用和更多属性,它可以为您提供更易读的代码。
不,那里没有。
在“Using Objects”部分页面下方约3/4:
VB:
With hero
.Name = "SpamMan"
.PowerLevel = 3
End With
C#:
//No "With" construct
hero.Name = "SpamMan";
hero.PowerLevel = 3;
我所做的是使用csharp ref关键字。例如:
ref MySubClassType e = ref MyMainClass.MySubClass;
然后你可以使用快捷方式:e.property
而不是MyMainClass.MySubClass.property
最简单的语法是:
{
var where = new MyObject();
where.property = "xxx";
where.SomeFunction("yyy");
}
{
var where = new MyObject();
where.property = "zzz";
where.SomeFunction("uuu");
}
实际上,如果你想重用变量名,那么额外的代码块非常方便。
有时您可以通过以下方式逃脱:
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的代码示例)