Com bloco equivalente em c #?

Eu sei VB.Net e estou tentando retocar meu c #. Existe um equivalente com bloco em c #?

obrigado

Embora o C # não tenha nenhum equivalente direto para o caso geral, o C # 3 ganha a syntax do inicializador de object para chamadas de construtor:

var foo = new Foo { Property1 = value1, Property2 = value2, etc }; 

Veja o capítulo 8 do C # em Depth para mais detalhes – você pode baixá-lo gratuitamente no site da Manning .

(Isenção de responsabilidade – sim, é do meu interesse colocar o livro nas mãos de mais pessoas. Mas, ei, é um capítulo gratuito que lhe dá mais informações sobre um tópico relacionado …)

É isso que o gerenciador de programas do Visual C # tem a dizer: Por que o C # não tem uma instrução ‘com’?

Muitas pessoas, incluindo os criadores de linguagem C #, acreditam que ‘com’ muitas vezes prejudica a legibilidade e é mais uma maldição do que uma bênção. É mais claro declarar uma variável local com um nome significativo e usar essa variável para executar várias operações em um único object, do que ter um bloco com um tipo de contexto implícito.

Como o Gerenciador de programas Visual C # vinculado acima, há situações limitadas em que a instrução With é mais eficiente, o exemplo que ele fornece quando está sendo usado como abreviação para acessar repetidamente uma expressão complexa.

Usando um método de extensão e genéricos, você pode criar algo que seja vagamente equivalente a uma instrução With, adicionando algo assim:

  public static T With(this T item, Action action) { action(item); return item; } 

Tomando um exemplo simples de como ele poderia ser usado, usando a syntax lambda você pode usá-lo para mudar algo como isto:

  updateRoleFamily.RoleFamilyDescription = roleFamilyDescription; updateRoleFamily.RoleFamilyCode = roleFamilyCode; 

Para isso:

  updateRoleFamily.With(rf => { rf.RoleFamilyDescription = roleFamilyDescription; rf.RoleFamilyCode = roleFamilyCode; }); 

Em um exemplo como este, a única vantagem é talvez um layout mais agradável, mas com uma referência mais complexa e mais propriedades, ele pode fornecer um código mais legível.

Não, não há.

Aproximadamente 3/4 abaixo da página na seção ” Usando Objetos “:

VB:

 With hero .Name = "SpamMan" .PowerLevel = 3 End With 

C #:

 //No "With" construct hero.Name = "SpamMan"; hero.PowerLevel = 3; 

Você poderia usar o padrão de acumulador de argumentos.

Grande discussão sobre isso aqui:

http://blogs.msdn.com/csharpfaq/archive/2004/03/11/87817.aspx

A syntax mais simples seria:

 { var where = new MyObject(); where.property = "xxx"; where.SomeFunction("yyy"); } { var where = new MyObject(); where.property = "zzz"; where.SomeFunction("uuu"); } 

Blocos de código realmente extras como esse são muito úteis se você quiser reutilizar nomes de variables.

Às vezes você pode fazer o seguinte:

 var fill = cell.Style.Fill; fill.PatternType = ExcelFillStyle.Solid; fill.BackgroundColor.SetColor(Color.Gray); fill.PatternColor = Color.Black; fill.Gradient = ... 

(Exemplo de código para EPPLus @ http://zeeshanumardotnet.blogspot.com )

Eu estava usando dessa maneira:

  worksheet.get_Range(11, 1, 11, 41) .SetHeadFontStyle() .SetHeadFillStyle(45) .SetBorders( XlBorderWeight.xlMedium , XlBorderWeight.xlThick , XlBorderWeight.xlMedium , XlBorderWeight.xlThick) ; 

SetHeadFontStyle / SetHeadFillStyle é ExtMethod do intervalo como abaixo:

  public static Range SetHeadFillStyle(this Range rng, int colorIndex) { //do some operation return rng; } 

fazer alguma operação e retornar o intervalo para a próxima operação

parece com o Linq 🙂

mas agora ainda não pode parecer totalmente – valor definido

 with cell.Border(xlEdgeTop) .LineStyle = xlContinuous .Weight = xlMedium .ColorIndex = xlAutomatic 

O que eu faço é usar uma palavra-chave csharp ref. Por exemplo:

 ref MySubClassType e = ref MyMainClass.MySubClass; 

você pode então usar o atalho como: e.property vez de MyMainClass.MySubClass.property

Um grande fã de With aqui!

Este é literalmente o meu código C # atual:

 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 }); } 

Em VB, pode ser:

 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 

Muito mais claro eu acho. Você poderia até mesmo ajustá-lo para ser mais conciso, ajustando a variável With . E, no estilo, ainda tenho escolha ! Talvez algo que o gerente do programa c # tenha esquecido.

Como um aparte, não é muito comum ver isso, mas eu usei na ocasião:

Ao invés de

 Using oClient As HttpClient = New HttpClient With oClient .BaseAddress = New Uri("http://mysite") .Timeout = New TimeSpan(123) .PostAsync( ... ) End With End Using 

Você pode usar

 With New HttpClient .BaseAddress = New Uri("http://mysite") .Timeout = New TimeSpan(123) .PostAsync( ... ) End With 

Você corre o risco de dar tapas no pulso - como eu por postar! - mas parece que você obtém todos os benefícios de uma declaração do Using em termos de descarte, etc, sem a rigidez extra.

NOTA: Isso pode dar errado ocasionalmente, portanto, use-o somente para código não crítico. Ou não de todo. Lembre-se: você tem uma escolha ...

Há outra uma implementação interessante de com padrão

 public static T With(this T o, params object[] pattern) => o; public static T To(this T o, out T x) => x = o; 

Você pode procurar mais detalhes pelo link e pesquisar amostras de códigos online .

Variações de uso

 static Point Sample0() => new Point().To(out var p).With( pX = 123, pY = 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( pX = 123, pY = 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( pX = 123, pY = 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); } 

Se você trabalha com estruturas [tipos de valor], o método de extensão semelhante também será útil

 public static TR Let(this T o, TR y) => y; 

Pode ser aplicado após o método With porque, por padrão, será retornada a cópia não modificada do struct

 struct Point { public double X; public double Y; public string Name; } static Point Sample0() => new Point().To(out var p).With( pX = 123, pY = 321, p.Name = "abc" ).Let(p); 

Aproveite se você gosta!

Se houver vários níveis de objects, você poderá obter uma funcionalidade semelhante com a diretiva “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; } 

Hmm. Eu nunca usei VB.net em profundidade, então estou fazendo uma suposição aqui, mas acho que o bloco ‘using’ pode estar perto do que você quer.

using define um escopo de bloco para uma variável, veja o exemplo abaixo

 using ( int temp = someFunction(param1) ) { temp++; // this works fine } temp++; // this blows up as temp is out of scope here and has been disposed 

Aqui está um artigo da Microsoft que explica um pouco mais


EDIT: sim, esta resposta está errada – a suposição original estava incorreta. O ‘WITH’ do VB é mais parecido com os novos inicializadores de objects C #:

 var yourVariable = new yourObject { param1 = 20, param2 = "some string" };