我知道VB.Net,正在尝试重新学习C#。C#中是否有一个With块等效项?
谢谢
我知道VB.Net,正在尝试重新学习C#。C#中是否有一个With块等效项?
谢谢
Answers:
这就是Visual C#程序管理器必须说的: 为什么C#没有'with'语句?
许多人,包括C#语言设计师在内,都认为“ with”通常会损害可读性,并且更多的是诅咒而不是祝福。声明具有有意义名称的局部变量,并使用该变量对单个对象执行多个操作要比拥有一个带有某种隐式上下文的块更为清楚。
get
与散落SKYLib.AccountsPayable.Client.ApiAuthorization.Authorization
代替With SKYLib.AccountsPayable.Client.ApiAuthorization.Authorization { .AuthToken = "123" .RefreshToken = "456" ... }
。
var auth = SKYLib.AccountsPayable.Client.ApiAuthorization.Authorization; auth.AuthToken = "123"; auth.RefreshToken = "456"; ...
。换句话说,可以通过准确地执行您抱怨的处方问题来解决您的问题。
{ var o = new object(); o.use (); ..}
到目前为止,手动创建该范围是唯一可行的方法。
尽管C#在一般情况下没有任何直接等效项,但是C#3为构造函数调用获取对象初始化器语法:
var foo = new Foo { Property1 = value1, Property2 = value2, etc };
有关更多详细信息,请参见C#中的第8章-您可以从以下位置免费下载它 Manning的网站。
(免责声明-是的,将本书交到更多人手中符合我的利益。但是,嘿,这是一个免费的章节,可为您提供有关相关主题的更多信息...)
With
但是,在仅使用with语句进行初始化的情况下,它仍然是相应的习惯用法。
with
被用于不可变类型,而不是普通的VB情况。
正如上面链接的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;
});
在这样的示例中,唯一的好处也许是布局更好,但是具有更复杂的引用和更多属性,它很可能使您的代码更具可读性。
var rf = myDataStructure.GetButton(44);
我根本看不到这是语法糖。这只是设置局部变量的复杂方法。“仅仅因为你做就意味着你不应该做。”
我要做的是使用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");
}
实际上,如果要重用变量名,像这样的额外代码块将非常方便。
该with
keywork在C#版本9中引入!您可以使用它来创建对象的副本,如下所示
Person brother = person with { FirstName = "Paul" };
“上面的行创建了一个新的Person记录,其中LastName属性是person的副本,FirstName是“ Paul”。您可以在with表达式中设置任意数量的属性。除“ clone”以外的任何合成成员该方法可能由您编写。如果记录类型的方法与任何合成方法的签名都匹配,则编译器不会合成该方法。”
更新:
在撰写此答案时,C#9尚未正式发布,而仅在预览中。但是,计划于2020年11月与.NET 5.0一起交付。
有关更多信息,请检查记录类型。
有时您可以执行以下操作:
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)
我正在使用这种方式:
worksheet.get_Range(11, 1, 11, 41)
.SetHeadFontStyle()
.SetHeadFillStyle(45)
.SetBorders(
XlBorderWeight.xlMedium
, XlBorderWeight.xlThick
, XlBorderWeight.xlMedium
, XlBorderWeight.xlThick)
;
SetHeadFontStyle / SetHeadFillStyle是范围的ExtMethod,如下所示:
public static Range SetHeadFillStyle(this Range rng, int colorIndex)
{
//do some operation
return rng;
}
做一些操作并返回范围以进行下一个操作
看起来像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
从处理等方面报表的,而无需额外的琐事。
注意:这有时可能会出错,因此仅将其用于非关键代码。还是根本没有。记住:您可以选择...
为了使生活更轻松,您可以使用垂直选择快速编辑内容
http://joelabrahamsson.com/select-columns-of-text-in-visual-studio/
另一种有趣的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;
用法变化
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
,但仅适用于static的方法或属性。例如
using static System.Math;
...
public double Area
{
get { return PI * Pow(Radius, 2); } // PI == System.Math.PI
}
更多信息:https : //docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/using-static
对我来说,我试图自动生成代码,并且需要为多个不同的类重用一个简单的变量,如“ x”,这样我就不必继续生成新的变量名。我发现,只要将代码放在花括号部分{}中,就可以限制变量的范围并多次重复使用它。
参见示例:
public class Main
{
public void Execute()
{
// Execute new Foos and new Bars many times with same variable.
double a = 0;
double b = 0;
double c = 0;
double d = 0;
double e = 0;
double f = 0;
double length = 0;
double area = 0;
double size = 0;
{
Foo x = new Foo(5, 6).Execute();
a = x.A;
b = x.B;
c = x.C;
d = x.D;
e = x.E;
f = x.F;
}
{
Bar x = new Bar("red", "circle").Execute();
length = x.Length;
area = x.Area;
size = x.Size;
}
{
Foo x = new Foo(3, 10).Execute();
a = x.A;
b = x.B;
c = x.C;
d = x.D;
e = x.E;
f = x.F;
}
{
Bar x = new Bar("blue", "square").Execute();
length = x.Length;
area = x.Area;
size = x.Size;
}
}
}
public class Foo
{
public int X { get; set; }
public int Y { get; set; }
public double A { get; private set; }
public double B { get; private set; }
public double C { get; private set; }
public double D { get; private set; }
public double E { get; private set; }
public double F { get; private set; }
public Foo(int x, int y)
{
X = x;
Y = y;
}
public Foo Execute()
{
A = X * Y;
B = X + Y;
C = X / (X + Y + 1);
D = Y / (X + Y + 1);
E = (X + Y) / (X + Y + 1);
F = (Y - X) / (X + Y + 1);
return this;
}
}
public class Bar
{
public string Color { get; set; }
public string Shape { get; set; }
public double Size { get; private set; }
public double Area { get; private set; }
public double Length { get; private set; }
public Bar(string color, string shape)
{
Color = color;
Shape = shape;
}
public Bar Execute()
{
Length = Color.Length + Shape.Length;
Area = Color.Length * Shape.Length;
Size = Area * Length;
return this;
}
}
在VB中,我将使用With变量,而根本不需要使用变量“ x”。不包括Foo和Bar的vb类定义,该vb代码为:
Public Class Main
Public Sub Execute()
Dim a As Double = 0
Dim b As Double = 0
Dim c As Double = 0
Dim d As Double = 0
Dim e As Double = 0
Dim f As Double = 0
Dim length As Double = 0
Dim area As Double = 0
Dim size As Double = 0
With New Foo(5, 6).Execute()
a = .A
b = .B
c = .C
d = .D
e = .E
f = .F
End With
With New Bar("red", "circle").Execute()
length = .Length
area = .Area
size = .Size
End With
With New Foo(3, 10).Execute()
a = .A
b = .B
c = .C
d = .D
e = .E
f = .F
End With
With New Bar("blue", "square").Execute()
length = .Length
area = .Area
size = .Size
End With
End Sub
End Class
嗯。我从未深度使用过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
编辑:是的,这个答案是错误的-最初的假设是不正确的。VB的“ WITH”更像是新的C#对象初始化程序:
var yourVariable = new yourObject { param1 = 20, param2 = "some string" };
using
不能使该值更短(从上面的答案中借来):using (var c=cell.Border(xlEdgeTop)) { c.LineStyle = xlContinuous; c.Weight = xlMedium; c.ColorIndex = xlAutomatic; }
如果存在多个级别的对象,则可以使用“ 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;
}