私はVB.Netを知っていて、C#をブラッシュアップしようとしています。 C#に同等のWithブロックはありますか?
ありがとう
C#には一般的な場合に直接相当するものはありませんが、C#3はコンストラクター呼び出しのオブジェクト初期化構文を取得します。
var foo = new Foo { Property1 = value1, Property2 = value2, etc };
詳細については、C#の第8章を参照してください。 ManningのWebサイト から無料でダウンロードできます。
(免責事項-はい、この本をより多くの人の手に届けることは私の利益です。しかし、ちょっと、それは関連するトピックに関する詳細情報を提供する無料の章です...)
これは、Visual C#プログラムマネージャーが言っていることです。 C#に「with」ステートメントがないのはなぜですか
C#言語のデザイナーを含む多くの人々は、「with」は読みやすさを損なうことが多く、祝福というよりも呪いだと考えています。ローカル変数を意味のある名前で宣言し、その変数を使用して単一のオブジェクトで複数の操作を実行する方が、一種の暗黙的なコンテキストを持つブロックを持つよりも明確です。
上記のVisual C#プログラムマネージャーが言うように、Withステートメントがより効率的である限られた状況があります。複雑な式に繰り返しアクセスするための短縮形として使用される場合の例です。
拡張メソッドとジェネリックを使用して、次のようなものを追加することで、Withステートメントと漠然と同等の何かを作成できます。
public static T With<T>(this T item, Action<T> action)
{
action(item);
return item;
}
ラムダ構文を使用する方法の簡単な例を取り上げると、ラムダ構文を使用して次のように変更できます。
updateRoleFamily.RoleFamilyDescription = roleFamilyDescription;
updateRoleFamily.RoleFamilyCode = roleFamilyCode;
これに:
updateRoleFamily.With(rf =>
{
rf.RoleFamilyDescription = roleFamilyDescription;
rf.RoleFamilyCode = roleFamilyCode;
});
このような例では、おそらく唯一の利点はレイアウトが優れていることですが、より複雑な参照とより多くのプロパティがあれば、コードが読みやすくなります。
いいえ、ありません。
「 sing 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 のコードサンプル)
ここで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 });
}
In 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
変数を調整することで、より簡潔にすることもできます。そして、スタイルに関しては、まだchoice!があります!おそらく、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
ステートメントのすべての利点を得るようです。
注:これはときどき間違っている可能性があるため、重要でないコードにのみ使用してください。またはまったくありません。覚えておいてください:あなたには選択肢があります...
私はこの方法を使用していました:
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-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 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