Мне нравится использовать LINQ для .net, но мне интересно узнать, как это работает внутри?
Кто-нибудь знает это?
Thks.
Мне нравится использовать LINQ для .net, но мне интересно узнать, как это работает внутри?
Кто-нибудь знает это?
Thks.
Спрашивается о конкретном аспекте LINQ. Это немного похоже на запрос "Как работает Windows" в противном случае.
Ключевые части LINQ для меня, с точки зрения С#:
Лямбда-выражения. Вот такие выражения:
x => x * 2
(int x, int y) => x * y
() => { Console.WriteLine("Block"); Console.WriteLine("Lambda"); }
Лямбда-выражения преобразуются либо в делегаты, либо в деревья выражений.
Анонимные типы. Вот такие выражения:
new { X=10, Y=20 }
Они все еще статически типизированы, просто компилятор генерирует неизменяемый тип для вас со свойствами X
и Y
. Они обычно используются с var
, который позволяет выводить тип локальной переменной из его выражения инициализации.
Выражения запроса. Вот такие выражения:
from person in people
where person.Age < 18
select person.Name
Они транслируются компилятором С# в "обычный" С# 3.0 (т.е. форма, которая не использует выражения запроса). После этого применяется разрешение перегрузки и т.д., Что является абсолютно ключом к возможности использования одного синтаксиса запроса с несколькими типами данных, без компилятора, имеющего какие-либо знания типов, таких как Queryable. Вышеприведенное выражение будет переведено на:
people.Where(person => person.Age < 18)
.Select(person => person.Name)
Методы расширения. Это статические методы, которые можно использовать так, как если бы они были методами экземпляра первого параметра. Например, метод расширения, подобный этому:
public static int CountAsciiDigits(this string text)
{
return text.Count(letter => letter >= '0' && letter <= '9');
}
можно использовать следующим образом:
string foo = "123abc456";
int count = foo.CountAsciiDigits();
Обратите внимание, что в реализации CountAsciiDigits
используется другой метод расширения, Enumerable.Count()
.
Это большинство соответствующих языковых аспектов. Тогда есть реализации стандартных операторов запросов, в LINQ-провайдерах, таких как LINQ to Objects и LINQ to SQL и т.д. У меня есть презентация о том, насколько разумно просто реализовать LINQ to Objects - это на "Talks" на веб-сайте С# в глубину.
Способ работы провайдеров, таких как LINQ to SQL, обычно осуществляется через класс Queryable
. По своей сути они преобразуют деревья выражений в другие форматы запросов, а затем создают соответствующие объекты с результатами выполнения этих внепроцессных запросов.
Это покрывает все, что вас интересует? Если есть что-то, о чем вы все еще хотите узнать, просто отредактируйте свой вопрос, и я поеду.
В простой форме компилятор принимает ваш кодовый запрос и преобразует его в кучу общих классов и вызовов. Ниже, в случае Linq2Sql, динамический SQL-запрос создается и выполняется с использованием DbCommand, DbDataReader и т.д.
Скажите, что у вас есть:
var q = from x in dc.mytable select x;
он преобразуется в следующий код:
IQueryable<tbl_dir_office> q =
dc.mytable.Select<tbl_dir_office, tbl_dir_office>(
Expression.Lambda<Func<mytable, mytable>>(
exp = Expression.Parameter(typeof(mytable), "x"),
new ParameterExpression[] { exp }
)
);
Множество дженериков, огромные накладные расходы.
LINQ в основном представляет собой комбинацию из С# 3.0 дискретных функций:
Для получения дополнительной информации о поездке туда (LINQ) см. это видео Anders в LANGNET 2008:
В основном linq представляет собой смесь некоторых языковых средств (компилятора) и некоторых расширений фреймворка. Поэтому, когда вы пишете запросы linq, они выполняются с использованием соответствующих интерфейсов, таких как IQuerable. Также обратите внимание, что среда выполнения не имеет роли в linq.
Но трудно ответить судье linq в короткий ответ. Я рекомендую вам прочитать какую-нибудь книгу. Я не уверен в книге, в которой рассказывается о внутренних компонентах Linq, но Linq in Action дает хорошие советы об этом.
У меня есть небольшая программа на С#, которая демонстрирует реализацию LINQ в С#.
class Program
{
static void Main(string[] args)
{
//Eventhough we call the method here, it gets called ONLY when the for loop is executed
var Cities = LinQFunction(new List<string>() { "Bangalore", "Mysore", "Coorg", "Tumkur", "Kerala", "TamilNadu" });
//LinQFunction() gets callled now
foreach(var city in Cities)
{
Console.WriteLine(city);
}
}
//This function is called ONLY when the foreach loop iterates and gets the item from the collection
static IEnumerable<string> LinQFunction(List<string> cities)
{
foreach (var item in cities)
{
//Return each 'item' at a time
yield return item;
}
}
}
Используйте соответствующие точки останова.