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

» Разработка > Кроссплатформенное использование классов .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С через ДобавитьОбработчик или ОбработкаВнешнегоСобытия
Поделиться с друзьями
-->

Комментарии (57)


  1. xGromMx
    06.09.2016 17:04
    +1

    Что делает «ъ»?


    1. Serginio1
      06.09.2016 17:11

      Так как в Native Api нельзя передавать объекты, то возвращается ссылка

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


      1. xGromMx
        06.09.2016 17:59
        +1

        Как вообще это читать?


        1. yarosroman
          06.09.2016 18:53
          +2

          хочется это развидеть.


      1. wildboar47
        07.09.2016 12:36

        почему нельзя было назвать это не «ъ» а «ВернутьСсылку»?


        1. Serginio1
          07.09.2016 12:38

          А почему в JQuery используют $ вместо JQuery. Просто очень много используетя в том числе и ъ(ъ(ъ
          Так удобнее для восприятия


          1. fishca
            07.09.2016 13:17
            -1

            Так удобнее для восприятия

            на фкус и свет у фсех фломастеры расные :D


  1. Serginio1
    06.09.2016 18:01
    +1

    Это код на 1С. Для начала нужно прочитать все статьи с начала.


    1. xGromMx
      06.09.2016 18:02
      +1

      Да у вас и .net код на русском написан


      1. Serginio1
        06.09.2016 18:09

        А зачем отказываться от Русслиша?
        Из статьи в статью только обращают на Русслиш. Что по теме понравилось, не понравилось.
        Если бы ты повнимательнее почитал статью то увидел Ужас

         var данныеЭкселя = Данные.GroupBy(ё => ё.НомСтроки).Select(ъ => new { НомСтроки = ъ.Key, Ячейки = ъ.ToArray() }).OrderBy(ь => ь.НомСтроки);
        


        1. xGromMx
          06.09.2016 18:20

          И это по твоему нормально выглядит?


          1. Serginio1
            06.09.2016 19:44

            Я не вижу разницы между

            var данныеЭкселя = Данные.GroupBy(i => i.НомСтроки).Select(n=> new { НомСтроки = n.Key, Ячейки = n.ToArray() }).OrderBy(j => j.НомСтроки);
            

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


            1. KvanTTT
              06.09.2016 20:02

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


              1. Serginio1
                06.09.2016 20:49

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


                1. KvanTTT
                  07.09.2016 00:06

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


                  1. Serginio1
                    07.09.2016 00:14
                    +1

                    Переменную нельзя а метод JQuery и все его прекрасно используют.
                    А насчет легче, то старое название еръ
                    значительно легче. Только вот смыл произношения при программировании? Особенно когда все поголовно используют сокращения. Смысл ъ как раз в том, что его никто практически не применяет и меньше конфликтов при одинаковом названии метода.


              1. dmpas
                06.09.2016 21:18

                я произношу эту букву по-старому: «ер». То же самое, что «и» или «ай».

                (ненене, сам я такие названия в коде не использую!)


            1. Shtucer
              07.09.2016 08:59
              +1

              Я увидел боль. Как эту кашу набирать-то…


              1. Serginio1
                07.09.2016 09:40
                -1

                Вот ты пишешь на форуме на русском, читаешь на русском. А примеры кода приводишь на английском. У тебя есть проблемы?
                Кроме того есть Punto с автопереключением. Очень удобно


                1. Shtucer
                  07.09.2016 09:44

                  Очень точное сравнение: что код писать, что в комментарии срать (или наоборот?) Пунто свитчер, как первейший инструмент программиста, да ещё с пометкой «очень удобно», это что-то новенькое. Но я не осуждаю, нет. Я как бы ошеломлён происходящим.


                  1. Serginio1
                    07.09.2016 09:55

                    Посмотри сколько у меня статей, и в комментариях одно и тоже. И главное, что суть статей то никто не обсуждает.


                    1. Shtucer
                      07.09.2016 09:57
                      +1

                      Потому что статьи хорошие, а обсуждальщики плохие.


                    1. denis_invader
                      07.09.2016 10:21

                      Потому что 90% статьи это код, а код похож на результат какого-то «генератора» для приколов. Лично я не могу этот код читать иначе как по-диагонали, смысл в нём найти очень сложно


                      1. Serginio1
                        07.09.2016 10:23

                        Спасибо. Буду стараться писать, что бы затронуло. Но проблема в том, что это статьи в основном для 1С ников. Хотя по динамическая компиляции в .Net Core очень мало информации.


                1. Shtucer
                  07.09.2016 09:49
                  +1

                  И это мы ещё не обсуждали смысловую нагрузку коротких именований. Для 'i' я могу придумать хоть какую-то смысл, это обычно первая буква от «index», или (реже) «iterator» Для ваших «ё» и «ъ» я тоже могу кое-что придумать, но это никак не относится к самой программе, тут, скорее всего, будет переход на личности.


            1. Sing
              07.09.2016 12:02

              Да, не несут. Именно поэтому так тоже не стоит писать. Бессмысленные названия переменных — это плохо. Для того, чтобы понять, что такое j придётся читать всю строку и осмысливать каждый метод.


              1. Serginio1
                07.09.2016 12:47

                А в Linq ты и так знаешь какой делегат от тебя ждут. Например

                public static IEnumerable<TSource> Where<TSource>(
                	this IEnumerable<TSource> source,
                	Func<TSource,?bool> predicate
                )
                

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


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


                1. Sing
                  07.09.2016 13:05

                  > Все сокращают, так как и так понятно, что это за переменная.

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

                  То есть

                  products.Where(p => p.Name == "Chair");
                  

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

                  уже не очень.


                  1. Serginio1
                    07.09.2016 13:37

                    На вкус и цвет… Никакой разницы между p и ё не вижу. Там хоть смайлик ставь.
                    Кстати Ограниченность набора символов Unicode для идентификаторов


                    1. fishca
                      07.09.2016 13:41

                      Все таки лучше идентификаторам давать осмысленные имена. Это признак хорошего программерского тона.


                      1. Serginio1
                        07.09.2016 13:46

                        И в чем «p» осмысленнее «ё»? Две буквы. Причем р еще можно читать и по русски


                        1. Sing
                          07.09.2016 15:44

                          Осмысленные — это типа «product».

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

                          Но я не могу придумать ни одной причины, почему список ячеек нужно сокращать до «ё». А когда идёт что-то типа «ё => ё.foo()» я читаю это как «ё моё».


                          1. Serginio1
                            07.09.2016 16:03

                            А можно и ёпрст или на ё бывает и за ё бывает


                            1. fishca
                              07.09.2016 16:28

                              Самое главное еще иметь чувство меры и баланса и не впадать в крайности давая идентификаторы типа: «ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент», при использовании таких даже широкоформатного монитора не хватает :)


                              1. Serginio1
                                07.09.2016 16:36

                                Зато понятно. Я кстати не против названия классов, особенно когда IntelliSense работает. И не нужно долго набирать или копировать.


                          1. Serginio1
                            07.09.2016 21:34

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

                            int main()
                            {
                                int ? = 2;
                                int ? = 4;
                                //int  = 5;
                                //int  = 6;
                                int 


                            1. fishca
                              07.09.2016 21:49

                              можно, только читабельность нулевая…


                              1. Serginio1
                                07.09.2016 21:54

                                Здесь не правильно отображает. Мне как раз глазастик понравился. Ооочень выразительный.


                      1. cleaner_it
                        08.09.2016 14:30

                        Я с вами согласен, в комментариях к прошлой статье об этом говорил. Большинство думает, что понятные имена — это «слишком длинно, и затрудняет чтение».

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


                        1. fishca
                          08.09.2016 16:39

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

                          Воистину так!


                          1. Serginio1
                            08.09.2016 17:34

                            Вот и я даю осмысленные имена. Только на русском. Я его значительно лучше понимаю англицкого


                            1. xGromMx
                              08.09.2016 19:28

                              Еще раз спрошу, в чем осмысленность «ъ»?


                              1. medvedevia
                                08.09.2016 20:03

                                О, а я смотрю Вы как раз на javascript программите, вот и расскажите нам в чем смысл $…


                                1. Serginio1
                                  08.09.2016 23:10

                                  Спасибо за поддержку. А то народ не интересует вызов управляемого кода из натива.
                                  Динамическая компиляция, рефлексия с выводом типа в дженериках и максимальная итд.
                                  Всех волнует только Руслиш и ъ.


                                1. Serginio1
                                  08.09.2016 23:11

                                  с


                              1. Serginio1
                                08.09.2016 23:07

                                Еще раз отвечу. ъ позаимствован из JQuery от $
                                Смысл тот же. Краткость и мало конфликтность. А конструкций типа ъ(ъ(ъ( много
                                и на каждом шагу к сожалению этот ъ нужно использовать. Просто давать что то осмысленное типа
                                ПолучитьОбъект(ПолучитьОбъект(ПолучитьОбъект(Объект.ВызватьМетод(Параметр.ПолучитьСсылку())))


  1. Serginio1
    06.09.2016 20:48

    А как удалить комментарий?


  1. fishca
    07.09.2016 09:31
    +1

    Вот зачем прикручивается кроссплатформенный С#, который все равно обращается к кроссплатформенному С++, если можно сразу на С++ все написать? Есть от этого какая-то выгода?


  1. Serginio1
    07.09.2016 09:37

    А можно на ссылочку на

    который все равно обращается к кроссплатформенному С++,


    Смысл в том, что можно использовать .Net сборки напрямую без дополнительного написания ВК. С С++ тебе нужно под каждую задачу делать ВК, знать С++.
    Здесь ты используешь уже готовые классы, либо пишешь сборку на .Net без всяких заморочек с ВК.
    То есть одна ВК через которую ты можешь использовать любые сборки. Не нужно знать C#, VB.NET,F#. Нужно знать только классы методы и свойства. Это аналог COM.


    1. fishca
      07.09.2016 13:25

      Почему бы не написать одну ВК на С++, а не С#? Тем более платформа 1С написана на С/С++, ОС-и тоже на нем же. Будет нативное взаимодействие. Зачем использовать прослойку в виде .Net?


      1. Serginio1
        07.09.2016 13:42

        ВК то написана на С++ но внутри используется доступ к статическим методам .Net библиотеки. А там через рефлексию можно вызвать методы объекта и статические методы. Почитай мои первые статьи.
        В C++ там не то, что рефлексии (динамический доступ к информации о методах и свойствах, но и вызов соответсвующих методов) нормальной информации о типе сложно получить.


      1. medvedevia
        07.09.2016 13:42

        А почему все не пишут на с/с++, если операционная система написана на с/с++? Вот и тут тоже самое…


        1. fishca
          07.09.2016 13:46

          Я еще могу понять использовать отличный от С/С++ язык для разработки какого-либо ПО, но вот использования виртуальных машин в виде .Net и Java я все равно до сих пор не могу понять. Явных преимуществ, сколько не пытался себя заставить, ну не вижу.


          1. Serginio1
            07.09.2016 13:52

            Кто тебе наплел про виртуальную машину? MSIL код компилируется в натив. Другое дело, что компилятор не оптимизирует код из-за наличия рефлексии. Сейчас есть .Net Native Компиляция приложений с помощью машинного кода .NET

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


            1. fishca
              07.09.2016 16:30

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

              Мне это не нужно. И я ничуть не хотел принизить твоих заслуг по написанию ВК. Но мне не понятно зачем Микрософт сделало прослойку .net, а потом все равно компиляцию в нативный код.


              1. Serginio1
                07.09.2016 16:42

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


                1. Serginio1
                  07.09.2016 19:36

                  Да еще компилируется лишь, то, что используется