На улице погода не очень, никуда не поехать, решил создать что то извращённое, больно уж захотелось… Предлагаю ниже код небольшой программы. Что она должна выдать на консоль? Скомпилируйте и проверьте себя...
Для тех кто понижает карму: не нравится пост переходите к другим темам. Он находится в персональном блоге. Комментировать ведь охото, а виртуалов я не создаю, не будьте так суровы…
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
namespace Frozik
{
static class Program
{
public static char FirstChar<TInput>(this TInput value)
where TInput: class
{
return value.ToString()[0];
}
static void Main()
{
var arguments = new List<string> { «arg_0», «temp_z», «arg_1», «arg_2»};
object locker;
lock (locker = new object())
{
Console.WriteLine(«Started»);
((Func<string>)(() =>
{
lock (locker)
{
var result = string.Empty;
foreach (string arg in
(from argEntity in arguments
where argEntity.StartsWith(«arg_»)
select argEntity.Substring(4)))
{
Console.WriteLine(result += arg.FirstChar<string>());
}
return result;
}
})).BeginInvoke(
(delegate (IAsyncResult result) {
Console.WriteLine(
new
{
Lenght =
((Func<string>)((AsyncResult)result).AsyncDelegate).
EndInvoke(result).Length
}.Lenght);
}),
new object()
);
Console.WriteLine(«Finished»);
Console.ReadKey();
}
Console.ReadKey();
}
}
}
Ниже даны объяснения, для тех, кому непонятен синтаксис
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
namespace Frozik
{
static class Program
{
// Создаём расширение для всех ссылочных типов, в моей программе расширение
// будет применяться только для string'ов. Расширение у меня generic только для того,
// чтобы побольше запутать.
// Как работают расширения:
// К любому стандартному и нестандартному типу можно добавить методы, как будто они
// были реализованы в самом классе. Далее в программе у меня используется расширение
// для строки — arg.FirstChar<string>()
// Расширения обязательно должны быть public static и создаваться в статическом классе
public static char FirstChar<TInput>(this TInput value)
// Расширение будет для ссылочных типов — generic типы доступны начиная с C# 2.0 и .Net 2.0
where TInput: class
{
return value.ToString()[0];
}
static void Main()
{
// Нововведение — за место вызова метода Add можно просто все данные указать как
// при объявлении массива. Также в данном случае arguments будет типа List<string>,
// intellisense это всё поймёт и будет корректно работать.
var arguments = new List<string> { «arg_0», «temp_z», «arg_1», «arg_2»};
object locker;
lock (locker = new object())
{
Console.WriteLine(«Started»);
// Лямбда выражение, по сути дела является анонимным делегатом. У стандартного типа
// Func (функция с возвращаемым параметром) можно также указать входные параметры
// которые в моём примере не нужны
// За место лямбда выражения можно было бы создать анонимный делегат
// (delegate () {
((Func<string>)(() =>
// Если бы стояла задача, мы могли бы написать следующее:
// Console.WriteLine(((Func<int, int, string>)((x, y) => (x+y).ToString()))(5, 5));
// Мы бы создали лямбда выражение, которое на вход имеет 2 параметра типа int, а на выходе
// string, и вызвали бы его с параметрами 5 и 5. Можете попробовать, это выведет 10 на консоль
// Пример в комментарии выше реализованный с помощью анонимного делегата -
// Console.WriteLine(((Func<int, int, string>)(delegate(int x, int y) { return (x + y).ToString(); }))(5, 5));
{
// Лямбда выражение имеет доступ до локальных переменных, которые были
// определены в методе родителя.
lock (locker)
{
// В данном случае result у нас будет типа string
var result = string.Empty;
foreach (string arg in
// Выражение Linq. Результат будет — IEnumerable<string>
// Мы ищем в arguments все значения, которые начинаются на «arg_»
// а в качестве результата берём только Substring(4) от каждого найденого
// результата. IEnumerable<string> легко превратить в List<string> или
// string[], достаточно просто вконце дописать .ToList() или ToArray()
// Также это выражение аналогично следующему -
// arguments.Where((argEntity) => argEntity.StartsWith(«arg_»)).
// Select((argEntity) => argEntity.Substring(4))
// Подробней можете посмотреть здесь — msdn2.microsoft.com/en-us/vcsharp/aa336746.aspx
(from argEntity in arguments
where argEntity.StartsWith(«arg_»)
select argEntity.Substring(4)))
{
// Складываем первые буквы строк и возвращаем результат сложения
Console.WriteLine(result += arg.FirstChar<string>());
}
return result;
}
})).
// Так как лямбда выражение может быть анонимным делегатом, то значит мы можем вызвать его
// в отдельном потоке
BeginInvoke(
// Создаем анонимный делегат, который будет вызван, когда запрос выполнится,
// за место этого можно было бы написать лямбда выражение
// (result) => {
(delegate (IAsyncResult result) {
Console.WriteLine(
// Создание типа на лету, у которого будет одно свойство Length,
// присутствует здесь только для того, чтобы побольше запутать
new
{
Lenght = ((Func<string>)((AsyncResult)result).AsyncDelegate).
EndInvoke(result).Length
}.
// Получение свойства Lenght у анонимного типа
Lenght);
}),
new object()
);
Console.WriteLine(«Finished»);
Console.ReadKey();
}
Console.ReadKey();
}
}
}
// Остались одни блокировки, но их объяснять не буду, это все должны знать ;-)
Для тех кто понижает карму: не нравится пост переходите к другим темам. Он находится в персональном блоге. Комментировать ведь охото, а виртуалов я не создаю, не будьте так суровы…
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
namespace Frozik
{
static class Program
{
public static char FirstChar<TInput>(this TInput value)
where TInput: class
{
return value.ToString()[0];
}
static void Main()
{
var arguments = new List<string> { «arg_0», «temp_z», «arg_1», «arg_2»};
object locker;
lock (locker = new object())
{
Console.WriteLine(«Started»);
((Func<string>)(() =>
{
lock (locker)
{
var result = string.Empty;
foreach (string arg in
(from argEntity in arguments
where argEntity.StartsWith(«arg_»)
select argEntity.Substring(4)))
{
Console.WriteLine(result += arg.FirstChar<string>());
}
return result;
}
})).BeginInvoke(
(delegate (IAsyncResult result) {
Console.WriteLine(
new
{
Lenght =
((Func<string>)((AsyncResult)result).AsyncDelegate).
EndInvoke(result).Length
}.Lenght);
}),
new object()
);
Console.WriteLine(«Finished»);
Console.ReadKey();
}
Console.ReadKey();
}
}
}
Ниже даны объяснения, для тех, кому непонятен синтаксис
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
namespace Frozik
{
static class Program
{
// Создаём расширение для всех ссылочных типов, в моей программе расширение
// будет применяться только для string'ов. Расширение у меня generic только для того,
// чтобы побольше запутать.
// Как работают расширения:
// К любому стандартному и нестандартному типу можно добавить методы, как будто они
// были реализованы в самом классе. Далее в программе у меня используется расширение
// для строки — arg.FirstChar<string>()
// Расширения обязательно должны быть public static и создаваться в статическом классе
public static char FirstChar<TInput>(this TInput value)
// Расширение будет для ссылочных типов — generic типы доступны начиная с C# 2.0 и .Net 2.0
where TInput: class
{
return value.ToString()[0];
}
static void Main()
{
// Нововведение — за место вызова метода Add можно просто все данные указать как
// при объявлении массива. Также в данном случае arguments будет типа List<string>,
// intellisense это всё поймёт и будет корректно работать.
var arguments = new List<string> { «arg_0», «temp_z», «arg_1», «arg_2»};
object locker;
lock (locker = new object())
{
Console.WriteLine(«Started»);
// Лямбда выражение, по сути дела является анонимным делегатом. У стандартного типа
// Func (функция с возвращаемым параметром) можно также указать входные параметры
// которые в моём примере не нужны
// За место лямбда выражения можно было бы создать анонимный делегат
// (delegate () {
((Func<string>)(() =>
// Если бы стояла задача, мы могли бы написать следующее:
// Console.WriteLine(((Func<int, int, string>)((x, y) => (x+y).ToString()))(5, 5));
// Мы бы создали лямбда выражение, которое на вход имеет 2 параметра типа int, а на выходе
// string, и вызвали бы его с параметрами 5 и 5. Можете попробовать, это выведет 10 на консоль
// Пример в комментарии выше реализованный с помощью анонимного делегата -
// Console.WriteLine(((Func<int, int, string>)(delegate(int x, int y) { return (x + y).ToString(); }))(5, 5));
{
// Лямбда выражение имеет доступ до локальных переменных, которые были
// определены в методе родителя.
lock (locker)
{
// В данном случае result у нас будет типа string
var result = string.Empty;
foreach (string arg in
// Выражение Linq. Результат будет — IEnumerable<string>
// Мы ищем в arguments все значения, которые начинаются на «arg_»
// а в качестве результата берём только Substring(4) от каждого найденого
// результата. IEnumerable<string> легко превратить в List<string> или
// string[], достаточно просто вконце дописать .ToList() или ToArray()
// Также это выражение аналогично следующему -
// arguments.Where((argEntity) => argEntity.StartsWith(«arg_»)).
// Select((argEntity) => argEntity.Substring(4))
// Подробней можете посмотреть здесь — msdn2.microsoft.com/en-us/vcsharp/aa336746.aspx
(from argEntity in arguments
where argEntity.StartsWith(«arg_»)
select argEntity.Substring(4)))
{
// Складываем первые буквы строк и возвращаем результат сложения
Console.WriteLine(result += arg.FirstChar<string>());
}
return result;
}
})).
// Так как лямбда выражение может быть анонимным делегатом, то значит мы можем вызвать его
// в отдельном потоке
BeginInvoke(
// Создаем анонимный делегат, который будет вызван, когда запрос выполнится,
// за место этого можно было бы написать лямбда выражение
// (result) => {
(delegate (IAsyncResult result) {
Console.WriteLine(
// Создание типа на лету, у которого будет одно свойство Length,
// присутствует здесь только для того, чтобы побольше запутать
new
{
Lenght = ((Func<string>)((AsyncResult)result).AsyncDelegate).
EndInvoke(result).Length
}.
// Получение свойства Lenght у анонимного типа
Lenght);
}),
new object()
);
Console.WriteLine(«Finished»);
Console.ReadKey();
}
Console.ReadKey();
}
}
}
// Остались одни блокировки, но их объяснять не буду, это все должны знать ;-)