Я знаю VB.Net и пытаюсь расчистить свой С#. Есть ли эквивалент С блочным эквивалентом в С#?
Спасибо
Я знаю VB.Net и пытаюсь расчистить свой С#. Есть ли эквивалент С блочным эквивалентом в С#?
Спасибо
Хотя С# не имеет прямого эквивалента для общего случая, С# 3 получает синтаксис инициализатора объекта для вызовов конструктора:
var foo = new Foo { Property1 = value1, Property2 = value2, etc };
Для более подробной информации смотрите главу 8 С# in Depth. Вы можете бесплатно скачать ее с веб-сайта Manning.
(Отказ от ответственности - да, в моих интересах, чтобы книга попала в руки большего количества людей. Но, эй, это бесплатная глава, которая дает вам больше информации по связанной теме...)
Это то, что менеджер программ Visual С# должен сказать: Почему С# не имеет инструкции 'with'?
Многие люди, включая дизайнеров языка С#, считают, что "с" часто наносит вред читаемости и является скорее бичем, чем благословением. это clearer, чтобы объявить локальную переменную со значимым именем и использовать эту переменную для выполнения нескольких операций на одном объекте, чем он должен иметь блок с своего рода неявным контекстом.
Как сказано выше в связке "Диспетчер программ Visual С#", существуют ограниченные ситуации, в которых оператор "С" более эффективен, пример, который он приводит, когда он используется в качестве сокращенной формы для многократного доступа к сложному выражению.
Используя метод расширения и обобщения, вы можете создать нечто, что примерно эквивалентно оператору 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;
});
В подобном примере единственным преимуществом, возможно, является более приятный макет, но с более сложной ссылкой и большим количеством свойств он может дать вам более читаемый код.
Нет, нет.
Около 3/4 вниз по странице в разделе Использование объектов:
VB:
With hero
.Name = "SpamMan"
.PowerLevel = 3
End With
С#:
//No "With" construct
hero.Name = "SpamMan";
hero.PowerLevel = 3;
Вы можете использовать шаблон аккумулятора аргумента.
Большое обсуждение здесь:
http://blogs.msdn.com/csharpfaq/archive/2004/03/11/87817.aspx
Я использую ключевое слово ref csharp. Например:
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)
Я использовал этот способ:
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
здесь!
Это буквально мой текущий код С#:
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
. И, по стилю, у меня все еще есть выбор! Возможно, менеджер программы С# упустил из виду.
Кроме того, это не очень часто можно увидеть, но я использовал это время от времени:
Вместо
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
с точки зрения утилизации и т.д. без лишних проблем.
ПРИМЕЧАНИЕ. Иногда это может пойти не так, поэтому используйте его только для некритического кода. Или нет совсем. Помните: у вас есть выбор...
Есть еще одна интересная реализация 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);
Наслаждайся, если хочешь!
Я думаю, что шкалой для "с" является 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
хмм. Я никогда не использовал 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
Вот статья от Microsoft, которая объясняет немного больше
ИЗМЕНИТЬ: да, этот ответ неверен - исходное предположение было неверным. VB 'WITH' больше похож на новые инициализаторы объектов С#:
var yourVariable = new yourObject { param1 = 20, param2 = "some string" };
Если существует несколько уровней объектов, вы можете получить аналогичную функциональность с помощью директивы "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;
}