Je connais VB.Net et j'essaie de rafraîchir mon C #. Existe-t-il un équivalent de bloc With en C #?
Merci
Bien que C # n'ait pas d'équivalent direct pour le cas général, C # 3 gagne la syntaxe d'initialisation d'objet pour les appels de constructeur:
var foo = new Foo { Property1 = value1, Property2 = value2, etc };
Voir le chapitre 8 de C # en profondeur pour plus de détails - vous pouvez le télécharger gratuitement sur site Web de Manning .
(Avertissement - oui, il est dans mon intérêt de mettre le livre entre les mains de plus de gens. Mais bon, c'est un chapitre gratuit qui vous donne plus d'informations sur un sujet connexe ...)
Voici ce que le gestionnaire de programme Visual C # a à dire: Pourquoi C # n'a-t-il pas une instruction 'with'?
Beaucoup de gens, y compris les concepteurs du langage C #, pensent que "avec" nuit souvent à la lisibilité, et est plus une malédiction qu'une bénédiction. Il est plus clair de déclarer une variable locale avec un nom significatif et d'utiliser cette variable pour effectuer plusieurs opérations sur un même objet que d'avoir un bloc avec une sorte de contexte implicite.
Comme le dit le gestionnaire de programmes Visual C # lié ci-dessus, il existe des situations limitées où l'instruction With est plus efficace, l'exemple qu'il donne lorsqu'il est utilisé comme raccourci pour accéder à plusieurs reprises à une expression complexe.
En utilisant une méthode d'extension et des génériques, vous pouvez créer quelque chose qui est vaguement équivalent à une instruction With, en ajoutant quelque chose comme ceci:
public static T With<T>(this T item, Action<T> action)
{
action(item);
return item;
}
En prenant un exemple simple de la façon dont il pourrait être utilisé, en utilisant la syntaxe lambda, vous pouvez ensuite l'utiliser pour changer quelque chose comme ceci:
updateRoleFamily.RoleFamilyDescription = roleFamilyDescription;
updateRoleFamily.RoleFamilyCode = roleFamilyCode;
Pour ça:
updateRoleFamily.With(rf =>
{
rf.RoleFamilyDescription = roleFamilyDescription;
rf.RoleFamilyCode = roleFamilyCode;
});
Sur un exemple comme celui-ci, le seul avantage est peut-être une mise en page plus agréable, mais avec une référence plus complexe et plus de propriétés, il pourrait bien vous donner un code plus lisible.
Non, il n'y en a pas.
Environ 3/4 en bas de la page dans la section " tilisation d'objets ":
VB:
With hero
.Name = "SpamMan"
.PowerLevel = 3
End With
C #:
//No "With" construct
hero.Name = "SpamMan";
hero.PowerLevel = 3;
Ce que je fais, c'est utiliser un mot clé ref csharp. Par exemple:
ref MySubClassType e = ref MyMainClass.MySubClass;
vous pouvez ensuite utiliser le raccourci comme: e.property
au lieu de MyMainClass.MySubClass.property
Vous pouvez utiliser le modèle d'accumulateur d'arguments.
Grande discussion à ce sujet ici:
http://blogs.msdn.com/csharpfaq/archive/2004/03/11/87817.aspx
La syntaxe la plus simple serait:
{
var where = new MyObject();
where.property = "xxx";
where.SomeFunction("yyy");
}
{
var where = new MyObject();
where.property = "zzz";
where.SomeFunction("uuu");
}
En fait, des blocs de code supplémentaires comme celui-ci sont très pratiques si vous souhaitez réutiliser les noms de variables.
Parfois, vous pouvez vous en tirer comme suit:
var fill = cell.Style.Fill;
fill.PatternType = ExcelFillStyle.Solid;
fill.BackgroundColor.SetColor(Color.Gray);
fill.PatternColor = Color.Black;
fill.Gradient = ...
(Exemple de code pour EPPLus @ http://zeeshanumardotnet.blogspot.com )
Un grand fan de With
ici!
C'est littéralement mon code C # actuel:
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 });
}
En VB cela pourrait être:
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
Beaucoup plus clair je pense. Vous pouvez même l'ajuster pour être plus concis en ajustant la variable With
. Et, en termes de style, j'ai encore choix! Peut-être quelque chose que le gestionnaire de programme C # a oublié.
Soit dit en passant, ce n'est pas très courant de voir cela, mais je l'ai utilisé à l'occasion:
Au lieu de
Using oClient As HttpClient = New HttpClient
With oClient
.BaseAddress = New Uri("http://mysite")
.Timeout = New TimeSpan(123)
.PostAsync( ... )
End With
End Using
Vous pouvez utiliser
With New HttpClient
.BaseAddress = New Uri("http://mysite")
.Timeout = New TimeSpan(123)
.PostAsync( ... )
End With
Vous risquez un claquement de poignet - tout comme moi pour poster! - mais il semble que vous bénéficiez de tous les avantages d'une déclaration Using
en termes d'élimination, etc. sans le rigmarole supplémentaire.
REMARQUE: cela peut parfois mal tourner, utilisez-le uniquement pour le code non critique. Ou pas du tout. N'oubliez pas: vous avez le choix ...
J'utilisais de cette façon:
worksheet.get_Range(11, 1, 11, 41)
.SetHeadFontStyle()
.SetHeadFillStyle(45)
.SetBorders(
XlBorderWeight.xlMedium
, XlBorderWeight.xlThick
, XlBorderWeight.xlMedium
, XlBorderWeight.xlThick)
;
SetHeadFontStyle/SetHeadFillStyle est ExtMethod de Range comme ci-dessous:
public static Range SetHeadFillStyle(this Range rng, int colorIndex)
{
//do some operation
return rng;
}
faire une opération et retourner le Range pour la prochaine opération
ça ressemble à Linq :)
mais maintenant il ne peut toujours pas lui ressembler complètement - valeur de réglage propery
with cell.Border(xlEdgeTop)
.LineStyle = xlContinuous
.Weight = xlMedium
.ColorIndex = xlAutomatic
Il existe une autre implémentation intéressante de 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;
Vous pouvez parcourir plus de détails par le lien et la recherche exemples de code en ligne .
Variations d'utilisation
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);
}
Si vous travaillez avec des structures [types de valeurs], la méthode d'extension similaire sera également utile
public static TR Let<T, TR>(this T o, TR y) => y;
Peut être appliqué après la méthode With car par défaut sera retournée la copie non modifiée de 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);
Profitez-en si vous le souhaitez!
Je pense que le truc des placards "avec" est static using
, mais ne fonctionne qu'avec les méthodes ou propriétés de static. par exemple.
using static System.Math;
...
public double Area
{
get { return PI * Pow(Radius, 2); } // PI == System.Math.PI
}
Plus d'informations: https://docs.Microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-static