.Net Core, 1C, динамическая компиляция, Scripting API

    Доброго времени суток хабратчане! Сегодня я продолжу мучить вас великим и могучим Руслишем. Это продолжение статей:

    » Разработка → Кроссплатформенное использование классов .Net из неуправляемого кода. Или аналог IDispatch на Linux
    » Разработка → Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux
    » Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux II
    » Асинхронное программирование в 1С через .Net Native ВК
    1С, Linux, Excel, Word, OpenXML,ADO и Net Core

    На данный момент в .Net Core 2 варианта динамической компиляции

    1. Это аналог CodeDom Microsoft.CodeAnalysis.CSharp.CSharpCompilation
    2. Roslyn Scripting Api. Примеры здесь

    var compilation = Microsoft.CodeAnalysis.CSharp.CSharpCompilation.Create("a")
        .WithOptions(new Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions(Microsoft.CodeAnalysis.OutputKind.DynamicallyLinkedLibrary))
        .AddReferences(
            Microsoft.CodeAnalysis.MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location))
            .AddSyntaxTrees(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseText(
            @"
              using System;
    
              public  class C
              {
      
                public  C(){}
                public string  M()
                  {
                   return ""Hello Roslyn."";
                 }
               }"));
    
                var fileName = @"d:\NetStandart\TestCoreNetApp\src\TestCoreNetApp\bin\Debug\netcoreapp1.0\a.dll";
    
                compilation.Emit(fileName);
    
                var a = System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromAssemblyPath(fileName);
    
    
                Type тип = a.GetType("C");
                var obj = Activator.CreateInstance(тип);
    
                var res = тип.GetMethod("M").Invoke(obj, null);
                Console.WriteLine(res.ToString());
    

    Этот подход хорош когда нужно обновить библиотеку. Но при этом создается DLL со всеми вытекающими.

    Второй способ мне нравится больше. Возьмем на примере получения делегата.

    string words = "надо заменить все первые буквы в словах на заглавные";
                string pattern = @"\w+";
                            
                var scr = Microsoft.CodeAnalysis.Scripting.ScriptOptions.Default;
                var mscorlib = Assembly.Load(System.Runtime.Loader.AssemblyLoadContext.GetAssemblyName(@"c:\Users\Smirnov_SA\.nuget\packages\Microsoft.NETCore.Portable.Compatibility\1.0.1\ref\netcore50\mscorlib.dll"));
                scr =scr.WithReferences(mscorlib, typeof(MulticastDelegate).GetTypeInfo().Assembly, typeof(System.Runtime.CompilerServices.IStrongBox).GetTypeInfo().Assembly, typeof(MatchEvaluator).GetTypeInfo().Assembly, typeof(Regex).GetTypeInfo().Assembly)
                .WithImports("System", "System.Text.RegularExpressions");
    
    
                string КодДелегата = @"return (MatchEvaluator)((match) =>
                {
                  string x = match.Value;
                // If the first char is lower case...
                    if (char.IsLower(x[0]))
                    {
                      // Capitalize it.
                        return char.ToUpper(x[0]) + x.Substring(1, x.Length - 1);
                    }
                      return x;
    
                });";
                var result = Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript.EvaluateAsync(КодДелегата, scr).Result;
                      MatchEvaluator evaluator = (MatchEvaluator)result;
                
                Console.WriteLine(Regex.Replace(words, pattern, evaluator));
    

    Обязательно нужно указать ссылки на:
    mscorlib.dll
    System.Private.CoreLib.ni.dll
    System.Runtime.dll

    Для компиляции используются следующие библиотеки:
    «Microsoft.CodeAnalysis.CSharp»: «2.0.0-beta3»,
    «Microsoft.CodeAnalysis.CSharp.Scripting»: «2.0.0-beta3»,
    «Microsoft.CodeAnalysis.Scripting.Common»: «2.0.0-beta3»,
    Microsoft.CodeAnalysis.Scripting

    По динамической компиляции. В свое время работал с запчастями для автомобилей. А там куча поставщиков и клиентов. При этом прайсы на миллионы позиций. И каждый горазд давать данные в своем формате. Было проще для каждого клиента создавать код записывать в справочник и использовать через Выполнить или Вычислить. Правда при работе с миллионными прайсами этот подход тормозил.

    Так или иначе приходилось писать DLL и работать через COM.

    C помощью динамической компиляции можно хранить текст кода и применять его в зависимости от условий. В том числе динамически формировать по условиям, а скомпилированный делегат можно кэшировать для повторного использования.
    Скорость компиляции достаточно высокая (кроме первого раза секунд 5).

    Перейдем к 1С. Так воторй алгоритм на 1С выглядит так

    стр  = "return (MatchEvaluator)((match) =>
                |{
                |  string x = match.Value;
                |// If the first char is lower case...
                |if (char.IsLower(x[0]))
                |{
                |// Capitalize it.
                |return char.ToUpper(x[0]) + x.Substring(1, x.Length - 1);
                |}
                |return x;
                |
                |});";
    			
    			текст = "надо заменить все первые буквы в словах на заглавные";
                Образец = "\w+";
                // MatchEvaluator evaluator = (MatchEvaluator)ПолучитьДелегат();
                ScriptOptions=ъТип("Microsoft.CodeAnalysis.Scripting.ScriptOptions","Microsoft.CodeAnalysis.Scripting");
    			CSharpScript=ъТип("Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript","Microsoft.CodeAnalysis.CSharp.Scripting");
    
                scr = ъ(ScriptOptions.Default);
                mscorlibСборка = ъ(Врап.Сборка("mscorlib.dll",Истина));
    	    Private_CoreLibСборка=ъ(Врап.Сборка("System.Private.CoreLib.ni",Истина));
    	   System_RuntimeСборка=ъ(Врап.Сборка("System.Runtime",Истина));
    	   RegularExpressionsСборка=ъ(Врап.Сборка("System.Text.RegularExpressions",Истина));
    	   Regex=ъ(RegularExpressionsСборка.GetType("System.Text.RegularExpressions.Regex"));
               scr =ъ(scr.WithReferences(mscorlibСборка.ПолучитьСсылку(), Private_CoreLibСборка.ПолучитьСсылку(), System_RuntimeСборка.ПолучитьСсылку(), RegularExpressionsСборка.ПолучитьСсылку()));
                
               scr =ъ(scr.WithImports("System", "System.Text.RegularExpressions"));
    
                evaluator = ъ(ъ(CSharpScript.EvaluateAsync(стр, scr.ПолучитьСсылку())).Result);
                Сообщить(Regex.Replace(текст, Образец, evaluator.ПолучитьСсылку()));
    

    В общем ничего особенного. Получили сборки, дали ссылки на них скомпилировали, вызвали.

    Перейдем к более сложным примерам. Так в предыдущей статье я показывал примеры использования DocumentFormat.OpenXml на примере чтения Excel и Word.

    Там была проблема в скорости из-за приведения строки к объекту через функцию ъ и сама скорость вызова из 1С в 5 раз медленнее её родного кода.

    Поэтому вынесем большую часть кода в .Net. Аналогичный вариант есть на большом .Net
    .Net в 1С. На примере использования HTTPClient,AngleSharp. Удобный парсинг сайтов с помощью библиотеки AngleSharp, в том числе с авторизацией аля JQuery с использованием CSS селекторов. Динамическая компиляция (пример в конце статьи).

    Создадим класс и скопируем его в макет. Суть класса прочитать данные ячеек и сгруппировать их по номеру строки.

    public class ДанныеЯчейки
        {
    
            public string ИмяЯчейки;
            public string ИмяКолонки;
            public int НомСтроки;
            public string ЗначениеЯчейки;
    
        }
        public class ExcelReader
        {
            static Regex ШаблонКолонки = new Regex("[A-Za-z]+");
            OpenXmlElementList ОбщиеСтроки;
    
            void ЗаписатьДанныеАдреса(string адрес, ДанныеЯчейки данныеЯчейки)
            {
    
                данныеЯчейки.ИмяЯчейки = адрес;
                var match = ШаблонКолонки.Match(адрес);
                var ИмяКолонки = match.Value;
                var НомерСтроки = int.Parse(адрес.Substring(ИмяКолонки.Length));
                данныеЯчейки.ИмяКолонки = ИмяКолонки;
                данныеЯчейки.НомСтроки = НомерСтроки;
    
            }
            void ДобавитьДанныеОбЯчейке(List<ДанныеЯчейки> ДанныеЭселя, Cell cell)
            {
                var адрес = cell.CellReference.InnerText;
                var text = cell.CellValue?.Text;
                var DataType = cell.DataType;
                string res = text;
                if (DataType != null && DataType == CellValues.SharedString)
                {
                    int ssid = int.Parse(text);
                    res = ОбщиеСтроки[ssid].InnerText;
                }
    
                if (res == null) return;
    
                var result = new ДанныеЯчейки();
                ЗаписатьДанныеАдреса(адрес, result);
                result.ЗначениеЯчейки = res;
    
                ДанныеЭселя.Add(result);
            }
            public List<ДанныеЯчейки> ReadExcel(string fileName)
            {
                List<ДанныеЯчейки> ДанныеЭселя = new List<ДанныеЯчейки>();
                using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    using (SpreadsheetDocument doc = SpreadsheetDocument.Open(fs, false))
                    {
                        var workbookPart = doc.WorkbookPart;
    
                        // Строки хранятся отдельно
                        // В ячейках хранится индекс
                        var pt = workbookPart.GetPartsOfType<SharedStringTablePart>();
                        var sstpart = pt.First();
                        var sst = sstpart.SharedStringTable;
                        ОбщиеСтроки = sst.ChildElements;
    
                        var workbook = workbookPart.Workbook;
    
                        // Получим список страниц
                        var sheet = workbook.Descendants<Sheet>().First();
    
                        var worksheetPart = (DocumentFormat.OpenXml.Packaging.WorksheetPart)workbookPart.GetPartById(sheet.Id);
    
                        var worksheet = worksheetPart.Worksheet;
    
                        var cells = worksheet.Descendants<Cell>();
    
    
                        // One way: go through each cell in the sheet
                        foreach (Cell cell in cells)
                        {
                            ДобавитьДанныеОбЯчейке(ДанныеЭселя, cell);
                        }
                    }
                }
    
                return ДанныеЭселя;
            }
    
            static string НайтиИмяПоследнейКолонки(List<ДанныеЯчейки> Тз)
            {
                var рез = "";
                var ДлинаРез = 0;
                foreach (var стрТз in Тз)
                {
                    var Стр = стрТз.ИмяКолонки;
                    var СтрДл = Стр.Length;
    
                    if (СтрДл > ДлинаРез)
                    {
                        ДлинаРез = СтрДл;
                        рез = Стр;
                    }
                    else if (СтрДл == ДлинаРез && string.Compare(Стр, рез, true) > 0)
                        рез = Стр;
    
                }
                return рез;
            }
    
            public static object ПолучитьДанныеЭкселя(string fileName)
            {
    
                var res = new ExcelReader();
                var Данные = res.ReadExcel(fileName);
                var данныеЭкселя = Данные.GroupBy(ё => ё.НомСтроки).Select(ъ => new { НомСтроки = ъ.Key, Ячейки = ъ.ToArray() }).OrderBy(ь => ь.НомСтроки);
                var ИмяПоследнейКолонки = НайтиИмяПоследнейКолонки(Данные);
                return new { ДанныеЁкселя = данныеЭкселя.ToList(), ИмяПоследнейКолонки = ИмяПоследнейКолонки };
    
            }
    
         }
    
                      return new Func<string, object>(ExcelReader.ПолучитьДанныеЭкселя);
    

    Мы описали класс чтения и возвращаем ссылку на делегат принимающий путь к файлу и возвращающий анонимный класс. Все равно в 1С мы будем работать с ним через рефлексию. Обратите внимание, что здесь описаны 2 класса.

    Теперь вызовем этот код из 1С.

    ScriptOptions=ъТип("Microsoft.CodeAnalysis.Scripting.ScriptOptions","Microsoft.CodeAnalysis.Scripting");
    	CSharpScript=ъТип("Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript","Microsoft.CodeAnalysis.CSharp.Scripting");
    	
    	scr = ъ(ScriptOptions.Default);
    	mscorlibСборка = ъ(Врап.Сборка("mscorlib.dll",Истина));
    	Private_CoreLibСборка=ъ(Врап.Сборка("System.Private.CoreLib.ni",Истина));
    	System_RuntimeСборка=ъ(Врап.Сборка("System.Runtime",Истина));
    	RegularExpressionsСборка=ъ(Врап.Сборка("System.Text.RegularExpressions",Истина));
    	OpenXmlСбока=ъ(Врап.Сборка("DocumentFormat.OpenXml.dll"));
    	LinqСбока=ъ(Врап.Сборка("System.Linq", истина));
    	FileSystemСбока=ъ(Врап.Сборка("System.IO.FileSystem", истина));
    	
    	Regex=ъ(RegularExpressionsСборка.GetType("System.Text.RegularExpressions.Regex"));
    	scr =ъ(scr.WithReferences(mscorlibСборка.ПолучитьСсылку(), Private_CoreLibСборка.ПолучитьСсылку(), System_RuntimeСборка.ПолучитьСсылку(), RegularExpressionsСборка.ПолучитьСсылку(),OpenXmlСбока.ПолучитьСсылку(),LinqСбока.ПолучитьСсылку(),FileSystemСбока.ПолучитьСсылку()));
    	scr =ъ(scr.WithImports("System", "System.Collections.Generic", "System.Linq", "System.IO", "DocumentFormat.OpenXml", "DocumentFormat.OpenXml.Packaging", "DocumentFormat.OpenXml.Spreadsheet", "System.Text.RegularExpressions"));
    	
    	Текст=ПолучитьМакет("ТекстКлассаЧтенияЕксель").ПолучитьТекст();
    	
    	Делегат = ъ(ъ(CSharpScript.EvaluateAsync(Текст, scr.ПолучитьСсылку())).Result);
    	Данные= ъ(Делегат.DynamicInvoke(ИмяФайла));
    	
    	Сообщить(Данные.ИмяПоследнейКолонки);
    	
    	рез=новый ТаблицаЗначений;
    	ПоследняяКолонка=Данные.ИмяПоследнейКолонки;
    	СоздатьКолонки(рез.Колонки,ПоследняяКолонка);
    	Колонки=рез.Колонки;
    	
    	Тз=ъ(Данные.ДанныеЁкселя);
    	Тз=ъ(Врап.ПолучитьЭнумератор(Тз.ПолучитьСсылку()));
    	
    	сч=1;
    	// Получили сгруппированные данные по строкам
    	Пока Тз.MoveNext() Цикл
    		стрТз= ъ(Тз.Current);
    		
    		НомСтроки=стрТз.НомСтроки;
    		Пока сч<НомСтроки Цикл
    			сч=сч+1;
    			рез.Добавить();
    		КонецЦикла;
    		сч=сч+1;
    		стр=рез.Добавить();
    		
                    // получим ячейки по строке
    		ТзГр=ъ(стрТз.Ячейки);
    		ТзГр=ъ(Врап.ПолучитьЭнумератор(ТзГр.ПолучитьСсылку()));
    		
    		Пока ТзГр.MoveNext() Цикл
    			стрТзГр= ъ(ТзГр.Current);
    			ИмяКолонки=стрТзГр.ИмяКолонки;
    			ЗначениеЯчейки=стрТзГр.ЗначениеЯчейки;
    			// Можно конечно получить индекс зная смещение символа 64 относительно 1 и 26 разрядную систему
    			// но найдем колонку по имени и её индекс
    			Колонка=Колонки.Найти(ИмяКолонки);
    			стр.Установить(Колонки.Индекс(Колонка),ЗначениеЯчейки); 
    		КонецЦикла;	
    	КонецЦикла;
    

    Теперь скорость обработки Экселя значительно увеличилась, а затраты на компиляцию соизмеримы с затратами на чтения файлов.

    Посмотрим процесс чтения Word. Не мудрствуя лукаво я взял готовый класс здесь. Тем более там все на англицком.

    
    // Исходники можно скачать здесь
        //https://code.msdn.microsoft.com/office/CSOpenXmlGetPlainText-554918c3/sourcecode?fileId=71592&pathId=851860130
        public class GetWordPlainText : IDisposable
        {
            // Specify whether the instance is disposed. 
            private bool disposed = false;
    
            // The word package 
            private WordprocessingDocument package = null;
    
            /// <summary> 
            ///  Get the file name 
            /// </summary> 
            private string FileName = string.Empty;
    
            /// <summary> 
            ///  Initialize the WordPlainTextManager instance 
            /// </summary> 
            /// <param name="filepath"></param> 
            public GetWordPlainText(string filepath)
            {
                this.FileName = filepath;
                if (string.IsNullOrEmpty(filepath) || !File.Exists(filepath))
                {
                    throw new Exception("The file is invalid. Please select an existing file again");
                }
    
                this.package = WordprocessingDocument.Open(filepath, true);
            }
    
            /// <summary> 
            ///  Read Word Document 
            /// </summary> 
            /// <returns>Plain Text in document </returns> 
            public string ReadWordDocument()
            {
                StringBuilder sb = new StringBuilder();
                OpenXmlElement element = package.MainDocumentPart.Document.Body;
                if (element == null)
                {
                    return string.Empty;
                }
    
                sb.Append(GetPlainText(element));
                return sb.ToString();
            }
    
            /// <summary> 
            ///  Read Plain Text in all XmlElements of word document 
            /// </summary> 
            /// <param name="element">XmlElement in document</param> 
            /// <returns>Plain Text in XmlElement</returns> 
            public string GetPlainText(OpenXmlElement element)
            {
                StringBuilder PlainTextInWord = new StringBuilder();
                foreach (OpenXmlElement section in element.Elements())
                {
                    switch (section.LocalName)
                    {
                        // Text 
                        case "t":
                            PlainTextInWord.Append(section.InnerText);
                            break;
    
                        case "cr":                          // Carriage return 
                        case "br":                          // Page break 
                            PlainTextInWord.Append(Environment.NewLine);
                            break;
    
                        // Tab 
                        case "tab":
                            PlainTextInWord.Append("\t");
                            break;
    
                        // Paragraph 
                        case "p":
                            PlainTextInWord.Append(GetPlainText(section));
                            PlainTextInWord.AppendLine(Environment.NewLine);
                            break;
    
                        default:
                            PlainTextInWord.Append(GetPlainText(section));
                            break;
                    }
                }
    
                return PlainTextInWord.ToString();
            }
    
            #region IDisposable interface 
    
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
    
            protected virtual void Dispose(bool disposing)
            {
                // Protect from being called multiple times. 
                if (disposed)
                {
                    return;
                }
    
                if (disposing)
                {
                    // Clean up all managed resources. 
                    if (this.package != null)
                    {
                        this.package.Dispose();
                    }
                }
    
                disposed = true;
            }
            #endregion
    
            public static string GetText(string FileName)
            {
    
                using (var pt = new GetWordPlainText(FileName))
                {
    
                    return pt.ReadWordDocument();
                }
            }
        }
        
        return new Func<string,string>(GetWordPlainText.GetText);
    

    Но вернемся к Руслишу:

    ScriptOptions=ъТип("Microsoft.CodeAnalysis.Scripting.ScriptOptions","Microsoft.CodeAnalysis.Scripting");
    	CSharpScript=ъТип("Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript","Microsoft.CodeAnalysis.CSharp.Scripting");
    	
    	scr = ъ(ScriptOptions.Default);
    	mscorlibСборка = ъ(Врап.Сборка("mscorlib.dll",Истина));
    	Private_CoreLibСборка=ъ(Врап.Сборка("System.Private.CoreLib.ni",Истина));
    	System_RuntimeСборка=ъ(Врап.Сборка("System.Runtime",Истина));
    	RegularExpressionsСборка=ъ(Врап.Сборка("System.Text.RegularExpressions",Истина));
    	OpenXmlСбока=ъ(Врап.Сборка("DocumentFormat.OpenXml.dll"));
    	LinqСбока=ъ(Врап.Сборка("System.Linq", истина));
    	FileSystemСбока=ъ(Врап.Сборка("System.IO.FileSystem", истина));
    	
    	Regex=ъ(RegularExpressionsСборка.GetType("System.Text.RegularExpressions.Regex"));
    	scr =ъ(scr.WithReferences(mscorlibСборка.ПолучитьСсылку(), Private_CoreLibСборка.ПолучитьСсылку(), System_RuntimeСборка.ПолучитьСсылку(),OpenXmlСбока.ПолучитьСсылку(),FileSystemСбока.ПолучитьСсылку()));
    	scr =ъ(scr.WithImports("System", "System.Text",  "System.IO", "DocumentFormat.OpenXml", "DocumentFormat.OpenXml.Packaging"));
    	
    	Текст=ПолучитьМакет("ТекстЧтенияВорд").ПолучитьТекст();
    	
    	Делегат = ъ(ъ(CSharpScript.EvaluateAsync(Текст, scr.ПолучитьСсылку())).Result);
    	стр = Делегат.DynamicInvoke(ИмяФайла);
    	
    	Текст=Новый ТекстовыйДокумент;
    	Текст.ДобавитьСтроку(стр);
    	Текст.Показать();
    

    Основная задача указать ссылки на используемые сборки и пространство имен.

    В следующей статье я сделаю динамическое создание обертки над объектами использующих события по аналогии с
    .NET(C#) для 1С. Динамическая компиляция класса обертки для использования .Net событий в 1С через ДобавитьОбработчик или ОбработкаВнешнегоСобытия
    Share post

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 57

      +1
      Что делает «ъ»?
        0
        Так как в Native Api нельзя передавать объекты, то возвращается ссылка

        //1С при передаче по ссылке свойства ВК Список.Current
        // при выходе из метода присваивает  Список.Current значение переданное изначально
        // Поэтому помечаем входной параметр как Знач
        //Или же делать так, если методы изменить нельзя 
        // То нужно присвоить значение переменной и вызвать метод передав в параметрах эту переменную
        //Стр=Список.Current; 
        //Зазача=ъ(Стр);
        Функция Ъ(знач Ссылка)
        	
        	// Создаем объект по ссылке полученной из методов .Net классов
        	//Физически это строка ёЁ<Ьъ>№_%)Э?&2 содержащее 12 символов для отделения их от других строк
        	//и индекс в спике исполуемых объектов на стороне .Net
        	
        	рез = Новый("AddIn.NetObjectToNative.NetObjectToNative");
        	// И установим ссылку
        	рез.УстановитьСсылку(Ссылка);    
        	возврат  рез
        КонецФункции // СоздатьОбъектПоСсылке()
        
        
          +1
          Как вообще это читать?
            +2
            хочется это развидеть.
            0
            почему нельзя было назвать это не «ъ» а «ВернутьСсылку»?
              0
              А почему в JQuery используют $ вместо JQuery. Просто очень много используетя в том числе и ъ(ъ(ъ
              Так удобнее для восприятия
                –1
                Так удобнее для восприятия

                на фкус и свет у фсех фломастеры расные :D
          +1
          Это код на 1С. Для начала нужно прочитать все статьи с начала.
            +1
            Да у вас и .net код на русском написан
              0
              А зачем отказываться от Русслиша?
              Из статьи в статью только обращают на Русслиш. Что по теме понравилось, не понравилось.
              Если бы ты повнимательнее почитал статью то увидел Ужас
               var данныеЭкселя = Данные.GroupBy(ё => ё.НомСтроки).Select(ъ => new { НомСтроки = ъ.Key, Ячейки = ъ.ToArray() }).OrderBy(ь => ь.НомСтроки);
              

                0
                И это по твоему нормально выглядит?
                  0
                  Я не вижу разницы между
                  var данныеЭкселя = Данные.GroupBy(i => i.НомСтроки).Select(n=> new { НомСтроки = n.Key, Ячейки = n.ToArray() }).OrderBy(j => j.НомСтроки);
                  

                  Никакой смысловой нагрузки они не несут. Так ты и не ответил, что кроме Русслиша ты увидел?

                    0

                    Название переменной i хотя бы можно кратко произнести, в отличие от ъ.

                      0
                      А как произносится $
                        0

                        Так переменную назвать нельзя. А произносится "доллар" легче, чем "твердый знак", да и используется реже.

                          +1
                          Переменную нельзя а метод JQuery и все его прекрасно используют.
                          А насчет легче, то старое название еръ
                          значительно легче. Только вот смыл произношения при программировании? Особенно когда все поголовно используют сокращения. Смысл ъ как раз в том, что его никто практически не применяет и меньше конфликтов при одинаковом названии метода.
                        0
                        я произношу эту букву по-старому: «ер». То же самое, что «и» или «ай».

                        (ненене, сам я такие названия в коде не использую!)
                        +1
                        Я увидел боль. Как эту кашу набирать-то…
                          –1
                          Вот ты пишешь на форуме на русском, читаешь на русском. А примеры кода приводишь на английском. У тебя есть проблемы?
                          Кроме того есть Punto с автопереключением. Очень удобно
                            0
                            Очень точное сравнение: что код писать, что в комментарии срать (или наоборот?) Пунто свитчер, как первейший инструмент программиста, да ещё с пометкой «очень удобно», это что-то новенькое. Но я не осуждаю, нет. Я как бы ошеломлён происходящим.
                              0
                              Посмотри сколько у меня статей, и в комментариях одно и тоже. И главное, что суть статей то никто не обсуждает.
                                +1
                                Потому что статьи хорошие, а обсуждальщики плохие.
                                  0
                                  Потому что 90% статьи это код, а код похож на результат какого-то «генератора» для приколов. Лично я не могу этот код читать иначе как по-диагонали, смысл в нём найти очень сложно
                                    0
                                    Спасибо. Буду стараться писать, что бы затронуло. Но проблема в том, что это статьи в основном для 1С ников. Хотя по динамическая компиляции в .Net Core очень мало информации.
                                +1
                                И это мы ещё не обсуждали смысловую нагрузку коротких именований. Для 'i' я могу придумать хоть какую-то смысл, это обычно первая буква от «index», или (реже) «iterator» Для ваших «ё» и «ъ» я тоже могу кое-что придумать, но это никак не относится к самой программе, тут, скорее всего, будет переход на личности.
                              0
                              Да, не несут. Именно поэтому так тоже не стоит писать. Бессмысленные названия переменных — это плохо. Для того, чтобы понять, что такое j придётся читать всю строку и осмысливать каждый метод.
                                0
                                А в Linq ты и так знаешь какой делегат от тебя ждут. Например
                                public static IEnumerable<TSource> Where<TSource>(
                                	this IEnumerable<TSource> source,
                                	Func<TSource, bool> predicate
                                )
                                

                                Но никто не пишет
                                 Where(ЭлементМассива =>ЭлементМассива >0)
                                


                                Все сокращают, так как и так понятно, что это за переменная. И искать особый смысл в них никто не ищет.
                                  0
                                  > Все сокращают, так как и так понятно, что это за переменная.

                                  ЕСЛИ понятно, что это за переменная. Переменная «ё» или «ъ» не даёт никакого понятия об этом.

                                  То есть
                                  products.Where(p => p.Name == "Chair");
                                  

                                  выглядит понятно, а
                                  Данные.GroupBy(ё => ё.НомСтроки)
                                  

                                  уже не очень.
                                    0
                                    На вкус и цвет… Никакой разницы между p и ё не вижу. Там хоть смайлик ставь.
                                    Кстати Ограниченность набора символов Unicode для идентификаторов
                                      0
                                      Все таки лучше идентификаторам давать осмысленные имена. Это признак хорошего программерского тона.
                                        0
                                        И в чем «p» осмысленнее «ё»? Две буквы. Причем р еще можно читать и по русски
                                          0
                                          Осмысленные — это типа «product».

                                          До одной буквы сокращают, когда из контекста очевидно, что за элемент мы используем.
                                          Например, у нас есть список products, productsArray, productsList и т.п. Соответственно, один элемент этого списка — product, сокращаем до первой буквы p. Как-то так

                                          Но я не могу придумать ни одной причины, почему список ячеек нужно сокращать до «ё». А когда идёт что-то типа «ё => ё.foo()» я читаю это как «ё моё».
                                            0
                                            А можно и ёпрст или на ё бывает и за ё бывает
                                              0
                                              Самое главное еще иметь чувство меры и баланса и не впадать в крайности давая идентификаторы типа: «ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент», при использовании таких даже широкоформатного монитора не хватает :)
                                                0
                                                Зато понятно. Я кстати не против названия классов, особенно когда IntelliSense работает. И не нужно долго набирать или копировать.

                                              0
                                              Кстати на С++ можно так здесь

                                              int main()
                                              {
                                                  int ➁ = 2;
                                                  int ➍ = 4;
                                                  //int  = 5;
                                                  //int  = 6;
                                                  int 
                                                0
                                                можно, только читабельность нулевая…
                                                  0
                                                  Здесь не правильно отображает. Мне как раз глазастик понравился. Ооочень выразительный.
                                            0
                                            Я с вами согласен, в комментариях к прошлой статье об этом говорил. Большинство думает, что понятные имена — это «слишком длинно, и затрудняет чтение».

                                            PS: А сколько раз меня выручали осмысленные наименования, когда приходится возвращаться к коду годичной давности!
                                              0
                                              PS: А сколько раз меня выручали осмысленные наименования, когда приходится возвращаться к коду годичной давности!

                                              Воистину так!
                                                0
                                                Вот и я даю осмысленные имена. Только на русском. Я его значительно лучше понимаю англицкого
                                                  0
                                                  Еще раз спрошу, в чем осмысленность «ъ»?
                                                    0
                                                    О, а я смотрю Вы как раз на javascript программите, вот и расскажите нам в чем смысл $…
                                                      0
                                                      Спасибо за поддержку. А то народ не интересует вызов управляемого кода из натива.
                                                      Динамическая компиляция, рефлексия с выводом типа в дженериках и максимальная итд.
                                                      Всех волнует только Руслиш и ъ.
                                                        0
                                                        с
                                                        0
                                                        Еще раз отвечу. ъ позаимствован из JQuery от $
                                                        Смысл тот же. Краткость и мало конфликтность. А конструкций типа ъ(ъ(ъ( много
                                                        и на каждом шагу к сожалению этот ъ нужно использовать. Просто давать что то осмысленное типа
                                                        ПолучитьОбъект(ПолучитьОбъект(ПолучитьОбъект(Объект.ВызватьМетод(Параметр.ПолучитьСсылку())))
                              0
                              А как удалить комментарий?
                                +1
                                Вот зачем прикручивается кроссплатформенный С#, который все равно обращается к кроссплатформенному С++, если можно сразу на С++ все написать? Есть от этого какая-то выгода?
                                  0
                                  А можно на ссылочку на
                                  который все равно обращается к кроссплатформенному С++,


                                  Смысл в том, что можно использовать .Net сборки напрямую без дополнительного написания ВК. С С++ тебе нужно под каждую задачу делать ВК, знать С++.
                                  Здесь ты используешь уже готовые классы, либо пишешь сборку на .Net без всяких заморочек с ВК.
                                  То есть одна ВК через которую ты можешь использовать любые сборки. Не нужно знать C#, VB.NET,F#. Нужно знать только классы методы и свойства. Это аналог COM.
                                    0
                                    Почему бы не написать одну ВК на С++, а не С#? Тем более платформа 1С написана на С/С++, ОС-и тоже на нем же. Будет нативное взаимодействие. Зачем использовать прослойку в виде .Net?
                                      0
                                      ВК то написана на С++ но внутри используется доступ к статическим методам .Net библиотеки. А там через рефлексию можно вызвать методы объекта и статические методы. Почитай мои первые статьи.
                                      В C++ там не то, что рефлексии (динамический доступ к информации о методах и свойствах, но и вызов соответсвующих методов) нормальной информации о типе сложно получить.
                                        0
                                        А почему все не пишут на с/с++, если операционная система написана на с/с++? Вот и тут тоже самое…
                                          0
                                          Я еще могу понять использовать отличный от С/С++ язык для разработки какого-либо ПО, но вот использования виртуальных машин в виде .Net и Java я все равно до сих пор не могу понять. Явных преимуществ, сколько не пытался себя заставить, ну не вижу.
                                            0
                                            Кто тебе наплел про виртуальную машину? MSIL код компилируется в натив. Другое дело, что компилятор не оптимизирует код из-за наличия рефлексии. Сейчас есть .Net Native Компиляция приложений с помощью машинного кода .NET

                                            Так создай мой аналог компоненты которая из 1С будет использовать любую библиотеку написанную на С++ без дополнительных телодвижений. В том числе и события.
                                              0
                                              Так создай мой аналог компоненты которая из 1С будет использовать любую библиотеку написанную на С++ без дополнительных телодвижений. В том числе и события.

                                              Мне это не нужно. И я ничуть не хотел принизить твоих заслуг по написанию ВК. Но мне не понятно зачем Микрософт сделало прослойку .net, а потом все равно компиляцию в нативный код.
                                                0
                                                Я не про заслуги, а про возможности. Зачем прослойка?
                                                1. Компоновка библиотек. Есть полная информация о типах и версиях.
                                                При этом библиотеки написанные под .Net 2.0 можно использовать под 4.5
                                                2. Независимость от процессора (AnyCPU)
                                                3. Рефлексия. За счет которой и создана данная ВК
                                                4. Динамическая компиляция.
                                                  0
                                                  Да еще компилируется лишь, то, что используется

                                    Only users with full accounts can post comments. Log in, please.