web-dev-qa-db-fra.com

Avec l'équivalent de bloc en C #?

Je connais VB.Net et j'essaie de rafraîchir mon C #. Existe-t-il un équivalent de bloc With en C #?

Merci

66
Dan Appleyard

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 ...)

55
Jon Skeet

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.

23
Gulzar Nazim

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.

21
RTPeat

Non, il n'y en a pas.

13
Guulh

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; 
11
Timothy Carter

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

4
Walter Zydhek

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

4
BBetances

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.

2
Wouter Schut

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 )

1
Sean

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 ...

1
SteveCinq

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
1
IlPADlI

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!

0
Makeman

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

0
Jaider