Что такое худшая ошибка в C # или .NET? [закрыто]

Другой способ использования Newtonsoft.Json :

dynamic stuff = Newtonsoft.Json.JsonConvert.DeserializeObject("{ color: 'red', value: 5 }");
string color = stuff.color;
int value = stuff.value;

375
задан 9 revs, 9 users 60% 13 August 2015 в 04:30
поделиться

48 ответов

private int myVar;
public int MyVar
{
    get { return MyVar; }
}

Blammo. Ваши сбои приложения без отслеживания стека. Происходит все время.

(Замечают капитал MyVar вместо нижнего регистра myVar в методе get.)

299
ответ дан 2 revs, 2 users 94% 13 August 2015 в 04:30
поделиться

Я видел, что этот отправил на днях, и я думаю, что это довольно неясно, и болезненно для тех, которые не знают

int x = 0;
x = x++;
return x;

, Когда это возвратится 0 и не 1, как большинство ожидало бы

44
ответ дан tvanfosson 13 August 2015 в 04:30
поделиться
  • 1
    Спасибо. Используйте $ (' #yourinput') .outerWidth (), хотя соответствовать входу реальная ширина – Romain Bruckert 28 September 2013 в 10:23

Если Вы кодируете для MOSS, и Вы добираетесь, сайт ссылаются на этот путь:

SPSite oSiteCollection = SPContext.Current.Site;

и позже в Вашем коде Вы говорите:

oSiteCollection.Dispose();

От MSDN:

при создании объекта SPSite можно использовать Расположить метод для закрытия объекта. Однако, если у Вас есть ссылка на совместно используемый ресурс, такой как тогда, когда объект обеспечивается методом GetContextSite или свойством Site (например, SPContext. Текущий. Сайт), не используйте Расположить метод, чтобы закрыть объект, но вместо этого позволить Windows SharePoint Services или Вашему приложению портала управлять объектом. Для получения дополнительной информации об объектном распоряжении, посмотрите Лучшие практики: Объекты Using Disposable Windows SharePoint Services.

Это происходит с каждым программистом MOSS и некоторой точкой.

6
ответ дан cciotti 13 August 2015 в 04:30
поделиться

Я часто должен напоминать мне, что DateTime является типом значения, не касательно типа. Просто кажется слишком странным мне, особенно рассматривая множество конструкторов для него.

5
ответ дан jcollum 13 August 2015 в 04:30
поделиться
  • 1
    можно изменить сплошной цвет на цвет, в котором Вы нуждаетесь – Mohamed Ibrahim 9 September 2013 в 08:30

Следующее не поймает исключение в.Net. Вместо этого это приводит к исключению StackOverflow.

private void button1_Click( object sender, EventArgs e ) {
    try {
        CallMe(234);
    } catch (Exception ex) {
        label1.Text = ex.Message.ToString();
    }
}
private void CallMe( Int32 x ) {
    CallMe(x);
}

Для комментаторов (и downvotes):
было бы чрезвычайно редко для переполнения стека быть этим очевидным. Однако, если Вы происходите, Вы не собираетесь ловить исключение и вероятно проведете несколько часов, пытаясь выследить точно, где проблема. Это может быть составлено, если ТАК происходит в небольших используемых логических путях, особенно на веб-приложении, где Вы не могли бы знать точные условия, которые начали проблему.

Это - та же самая ситуация как принятый ответ на этот вопрос ( https://stackoverflow.com/a/241194/2424). Метод get свойства на том ответе по существу делает ту же самую вещь как вышеупомянутый код и отказывает без отслеживания стека.

1
ответ дан 3 revs 13 August 2015 в 04:30
поделиться
mystring.Replace("x","y")

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

0
ответ дан 3 revs, 2 users 50% 13 August 2015 в 04:30
поделиться
  • 1
    Было супер полезно, что Вы показали " передайте свои переменные закрытию с помощью use ($contactEmail, $contactName) ". я никогда не знал, как передать переменные закрытию. Спасибо! – Ryan 25 January 2014 в 19:35

Существует целая книга по Глюки.NET

, Моим фаворитом является тот, где Вы создаете класс в C#, наследовали его к VB и затем пытаетесь повторно наследоваться назад к C#, и он не работает. ARGGH

8
ответ дан MikeJ 13 August 2015 в 04:30
поделиться

Тип. GetType

тот, который я видел, кусает много людей, Type.GetType(string) . Они задаются вопросом, почему это работает на типы в их собственном блоке и некоторые типы как System.String, но не System.Windows.Forms.Form. Ответ - то, что это только смотрит в текущем блоке и в mscorlib.

<час>

Анонимные методы

C# 2.0 представил анонимные методы, ведя к противным таким ситуациям:

using System;
using System.Threading;

class Test
{
    static void Main()
    {
        for (int i=0; i < 10; i++)
        {
            ThreadStart ts = delegate { Console.WriteLine(i); };
            new Thread(ts).Start();
        }
    }
}

, Что это распечатает? Ну, это полностью зависит от планирования. Это распечатает 10 чисел, но это, вероятно, не распечатает 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, который является тем, что Вы могли бы ожидать. Проблема состоит в том, что это i переменная, которая была получена, не ее значение при создании делегата. Это может быть решено легко с дополнительной локальной переменной правильного объема:

using System;
using System.Threading;

class Test
{
    static void Main()
    {
        for (int i=0; i < 10; i++)
        {
            int copy = i;
            ThreadStart ts = delegate { Console.WriteLine(copy); };
            new Thread(ts).Start();
        }
    }
}
<час>

Задержанное выполнение блоков итератора

модульный тест Этого "бедного человека" не передает - почему нет?

using System;
using System.Collections.Generic;
using System.Diagnostics;

class Test
{
    static IEnumerable<char> CapitalLetters(string input)
    {
        if (input == null)
        {
            throw new ArgumentNullException(input);
        }
        foreach (char c in input)
        {
            yield return char.ToUpper(c);
        }
    }

    static void Main()
    {
        // Test that null input is handled correctly
        try
        {
            CapitalLetters(null);
            Console.WriteLine("An exception should have been thrown!");
        }
        catch (ArgumentNullException)
        {
            // Expected
        }
    }
}

ответ - то, что код в источнике эти CapitalLetters код не становится выполняемым до итератора MoveNext(), метод сначала называют.

у меня есть некоторые другие причуды на моем страница .

головоломок
252
ответ дан Jon Skeet 13 August 2015 в 04:30
поделиться
  • 1
    Ваш ответ вводит в заблуждение, потому что Dictionary<TKey, TValue> использование EqualityComparer<T>.Default для сравнений и того компаратора не использует оператор == для сравнений. Оператор == абсолютно не важен этому вопросу. – Sam Harwell 10 May 2013 в 00:04

Вот другой тот времени, который получает меня:

static void PrintHowLong(DateTime a, DateTime b)
{
    TimeSpan span = a - b;
    Console.WriteLine(span.Seconds);        // WRONG!
    Console.WriteLine(span.TotalSeconds);   // RIGHT!
}
<час>

TimeSpan. Секунды являются частью секунд промежутка (2 минуты, и 0 секунд имеет значение секунд 0).

TimeSpan. TotalSeconds является всем промежутком, измеренным в секундах (2 минуты имеет общее значение секунд 120).

144
ответ дан Jon B 13 August 2015 в 04:30
поделиться
  • 1
    @280Z28 OP, который попросили подробного объяснения поведения, он добирался. Я интерпретировал вопрос как признак, что OP имел недоразумение о равенстве.NET в целом и что проблемой с ключами словаря является просто конкретное проявление того недоразумения. Так, я пытался ответить на вопрос в способе, которым я верю, является самым полезным. Я предполагаю, что Вы могли рассмотреть более широкое обобщение как частично " off-topic" но that' s мое объяснение для моего ответа. – smartcaveman 19 June 2013 в 12:55

Повторно выдавая исключения

глюк А, который получает много новых разработчиков, является семантикой исключения переброска.

Партии времени я вижу код как следующий

catch(Exception e) 
{
   // Do stuff 
   throw e; 
}

, проблема состоит в том, что это вытирает отслеживание стека и делает проблемы диагностирования намного тяжелее, причина, которую Вы не можете отследить где порожденное исключение.

корректный код является любой оператором броска без args:

catch(Exception)
{
    throw;
}

Или обертывание исключения в другом и использования внутреннего исключения для получения исходного отслеживания стека:

catch(Exception e) 
{
   // Do stuff 
   throw new MySpecialException(e); 
}
193
ответ дан 4 revs, 2 users 89% 13 August 2015 в 04:30
поделиться
  • 1
    @280Z28, that' s положительная сторона - я обновил свой ответ для обращения к этому. – smartcaveman 10 May 2013 в 01:13

Если бы Вы считаете ASP.NET, я сказал бы, что жизненный цикл веб-форм является довольно большим глюком мне. Я провел бесчисленные часы, отлаживая плохо записанный код веб-форм, просто потому что много разработчиков просто действительно не понимает, когда использовать, какой обработчик событий (меня включал, печально).

51
ответ дан Erik van Brakel 13 August 2015 в 04:30
поделиться
  • 1
    Я должен был сделать то же для .tt-hint также, но это работало на меня. – Steve 15 May 2014 в 18:51

перегруженный == операторы и невведенные контейнеры (arraylists, наборы данных, и т.д.):

string my = "my ";
Debug.Assert(my+"string" == "my string"); //true

var a = new ArrayList();
a.Add(my+"string");
a.Add("my string");

// uses ==(object) instead of ==(string)
Debug.Assert(a[1] == "my string"); // true, due to interning magic
Debug.Assert(a[0] == "my string"); // false

Решения?

  • всегда использование string.Equals(a, b), когда Вы сравниваете строковые типы

  • дженерики использования как List<string>, чтобы гарантировать, что оба операнда являются строками.

49
ответ дан Rob 13 August 2015 в 04:30
поделиться

Когда Вы запускаете процесс (использующий Систему. Диагностика), который пишет в консоль, но Вы никогда не читаете Консоль. Поток, после определенного количества вывода Ваше приложение, будет казаться, зависнет.

37
ответ дан user25306 13 August 2015 в 04:30
поделиться

Объекты значения в изменяемых наборах

struct Point { ... }
List<Point> mypoints = ...;

mypoints[i].x = 10;

не имеют никакого эффекта.

mypoints[i] возвраты копия Point объект значения. C# счастливо позволяет Вам изменить поле копии. Тихо выполнение ничего.

<час>

Обновление: Это, кажется, фиксируется в C# 3.0:

Cannot modify the return value of 'System.Collections.Generic.List<Foo>.this[int]' because it is not a variable
27
ответ дан 5 revs, 2 users 97% 13 August 2015 в 04:30
поделиться

Сборка "мусора" и Располагает (). Хотя Вы ничего не должны делать к свободному память , все еще необходимо освободить , ресурсы через Располагают (). Это - очень легкая вещь забыть, когда Вы используете WinForms или отслеживаете объекты всегда.

19
ответ дан Jeff Kotula 13 August 2015 в 04:30
поделиться

объем переменных циклов foreach!

var l = new List<Func<string>>();
var strings = new[] { "Lorem" , "ipsum", "dolor", "sit", "amet" };
foreach (var s in strings)
{
    l.Add(() => s);
}

foreach (var a in l)
    Console.WriteLine(a());

печать пять "amet", в то время как следующий пример хорошо работает

var l = new List<Func<string>>();
var strings = new[] { "Lorem" , "ipsum", "dolor", "sit", "amet" };
foreach (var s in strings)
{
    var t = s;
    l.Add(() => t);
}

foreach (var a in l)
    Console.WriteLine(a());
18
ответ дан Brian J Cardiff 13 August 2015 в 04:30
поделиться
  • 1
    На самом деле собираясь наталкиваться это, чтобы быть ответом начиная с другого ответа вызвало непредвиденные проблемы, когда я дал ему кредит. Это - окончательный ответ, который я использовал:) – zmanc 9 June 2013 в 00:05

MemoryStream.GetBuffer() по сравнению с MemoryStream.ToArray(). Бывшие возвраты целый буфер, последний просто используемая часть. Фу.

7
ответ дан 2 revs, 2 users 67% 13 August 2015 в 04:30
поделиться

Мой худший до сих пор я просто выяснил сегодня... Если Вы переопределяете объект. Равняется (возразите obj), можно волновать обнаружение что:

((MyObject)obj).Equals(this);

не ведет себя то же как:

((MyObject)obj) == this;

Каждый вызовет Вашу переопределенную функцию, другой НЕ будет.

5
ответ дан GWLlosa 13 August 2015 в 14:30
поделиться

Для программистов C/C++ переход к C# является естественным. Однако самый большой глюк я столкнулся лично (и видели с другими, делающими тот же переход), не полностью понимает различия между классами и структурами в C#.

В C++, классы и структуры идентичны; они только отличаются по видимости по умолчанию, где значение по умолчанию классов к частной видимости и значение по умолчанию структур к общедоступной видимости. В C++ это определение класса

    class A
    {
    public:
        int i;
    };

функционально эквивалентно этому определению структуры.

    struct A
    {
        int i;
    };

В C#, однако, классы являются ссылочными типами, в то время как структуры являются типами значения. Это делает БОЛЬШОЙ различие в (1) решении, когда использовать один по другому, (2) тестировании объектного равенства, (3) производительности (например, упаковывая/распаковывая), и т.д.

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

22
ответ дан Matt Davis 13 August 2015 в 14:30
поделиться

DateTime.ToString ("дд / ММ / гггг") ; На самом деле это будет не всегда давать вам dd / MM / yyyy, а вместо этого будет учитывать региональные настройки и заменять разделитель даты в зависимости от того, где вы находитесь. Так что вы можете получить dd-MM-yyyy или что-то подобное.

Правильный способ сделать это - использовать DateTime.ToString ("dd '/' MM '/' yyyy");


DateTime. ToString ("r") должен преобразовывать в RFC1123, который использует GMT. GMT находится в пределах доли секунды от UTC, но спецификатор формата «r» не преобразуется в UTC , даже если рассматриваемый DateTime указан как Local.

Это приводит к следующему Попался (зависит от того, насколько далеко ваше местное время от UTC):

DateTime.Parse("Tue, 06 Sep 2011 16:35:12 GMT").ToString("r")
>              "Tue, 06 Sep 2011 17:35:12 GMT"

Упс!

46
ответ дан 22 November 2019 в 23:57
поделиться

Сегодня я исправил ошибку, которая долго ускользала. Ошибка была в универсальном классе, который использовался в многопоточном сценарии, а поле static int использовалось для обеспечения синхронизации без блокировки с помощью Interlocked. Ошибка была вызвана тем, что каждый экземпляр универсального класса для типа имеет свой статический код. Таким образом, каждый поток получил свое собственное статическое поле, и он не использовал блокировку, как предполагалось.

class SomeGeneric<T>
{
    public static int i = 0;
}

class Test
{
    public static void main(string[] args)
    {
        SomeGeneric<int>.i = 5;
        SomeGeneric<string>.i = 10;
        Console.WriteLine(SomeGeneric<int>.i);
        Console.WriteLine(SomeGeneric<string>.i);
        Console.WriteLine(SomeGeneric<int>.i);
    }
}

Это печатает 5 10 5

14
ответ дан 22 November 2019 в 23:57
поделиться

An option would be to have the Abstract class do the calling in this manner. Otherwise, there is no way in c# to require an inherited class to implement a method in a certain way.

public abstract class AbstractClass
{
    public void PerformThisFunction()
    {
        MustBeCalled();
        AbstractMethod();
    }

    public void MustBeCalled()
    {
        //this must be called when AbstractMethod is invoked
    }

    //could also be public if desired
    protected abstract void AbstractMethod();
}

public class ImplementClass : AbstractClass
{
    protected override void AbstractMethod()
    {
        //when called, base.MustBeCalled() must be called.
        //how can i enforce this?
    }
}

Doing this creates the desired public facing method in the abstract class, giving the abstract class over how and in what order things are called, while still allowing the concrete class to provide needed functionality.

он не даст вам полного пути:

Этот код:

string prefix1 = "C:\\MyFolder\\MySubFolder";
string prefix2 = "C:\\MyFolder\\MySubFolder\\";
string suffix1 = "log\\";
string suffix2 = "\\log\\";

Console.WriteLine(Path.Combine(prefix1, suffix1));
Console.WriteLine(Path.Combine(prefix1, suffix2));
Console.WriteLine(Path.Combine(prefix2, suffix1));
Console.WriteLine(Path.Combine(prefix2, suffix2));

Дает вам следующий результат:

C:\MyFolder\MySubFolder\log\
\log\
C:\MyFolder\MySubFolder\log\
\log\
40
ответ дан 22 November 2019 в 23:57
поделиться
[Serializable]
class Hello
{
    readonly object accountsLock = new object();
}

//Do stuff to deserialize Hello with BinaryFormatter
//and now... accountsLock == null ;)

Мораль истории: инициализаторы полей не запускаются при десериализации объекта

48
ответ дан 22 November 2019 в 23:57
поделиться

MS SQL Server не может обрабатывать даты до 1753 года. Примечательно, что это не синхронизировано с константой .NET DateTime.MinDate , которая равна 1 / 1/1. Так что если вы попытаетесь сохранить память, неверную дату (как недавно случилось со мной при импорте данных) или просто дату рождения Вильгельма Завоевателя, у вас будут проблемы. Для этого нет встроенного обходного пути; если вам, вероятно, понадобится работать с датами до 1753 года, вам нужно написать собственный обходной путь.

у тебя будут проблемы. Для этого нет встроенного обходного пути; если вам, вероятно, потребуется работать с датами до 1753 года, вам нужно написать собственный обходной путь.

у тебя будут проблемы. Для этого нет встроенного обходного пути; если вам, вероятно, потребуется работать с датами до 1753 года, вам нужно написать собственный обходной путь.

18
ответ дан 22 November 2019 в 23:57
поделиться

Утечка памяти из-за того, что вы не отключили события.

Это даже зацепило некоторых старших разработчиков, которых я знаю.

Представьте себе форму WPF с большим количеством вещей в ней, и где-то там вы подписываетесь на событие. Если вы не откажетесь от подписки, то после закрытия и отмены ссылки вся форма будет храниться в памяти.

Я считаю, что проблема, которую я видел, заключалась в создании DispatchTimer в форме WPF и подписке на событие Tick, если вы этого не сделаете. 'Не делайте - = на таймере, ваша форма утекает память!

В этом примере ваш код разрыва должен иметь

timer.Tick -= TimerTickEventHandler;

Это особенно сложно, поскольку вы создали экземпляр DispatchTimer внутри формы WPF, поэтому вы можете подумать что это будет внутренняя ссылка, обрабатываемая процессом сборки мусора ...

80
ответ дан 22 November 2019 в 23:57
поделиться

Неприятная ошибка кеширования Linq

См. мой вопрос , который привел к этому открытию, и блоггера , обнаружившего проблему.

Короче говоря, DataContext хранит кеш всех объектов Linq-to-Sql, которые вы когда-либо загружали. Если кто-то еще внесет какие-либо изменения в ранее загруженную вами запись, вы не сможете получить последние данные, , даже если вы явно перезагрузите запись!

Это из-за свойства с именем ObjectTrackingEnabled в DataContext, что по умолчанию истинно. Если вы установите для этого свойства значение false, запись будет загружаться заново каждый раз ... НО ... вы не можете сохранить какие-либо изменения в этой записи с помощью SubmitChanges ().

GOTCHA!

18
ответ дан 22 November 2019 в 23:57
поделиться

Может быть, это не совсем проблема, потому что поведение ясно написано в MSDN, но однажды сломал мне шею, потому что я нашел его довольно нелогичным:

Image image = System.Drawing.Image.FromFile("nice.pic");

Этот парень уходит из " nice.pic " файл заблокирован, пока изображение не будет удалено. В то время, когда я столкнулся с этим, я подумал, что было бы неплохо загружать значки на лету, и не осознавал (сначала), что у меня были десятки открытых и заблокированных файлов! Изображение отслеживает, откуда был загружен файл ...

Как решить эту проблему? Я думал, что одинарный лайнер сработает. Я ожидал, что для FromFile () появится дополнительный параметр, но его не было, поэтому я написал это ...

using (Stream fs = new FileStream("nice.pic", FileMode.Open, FileAccess.Read))
{
    image = System.Drawing.Image.FromStream(fs);
}
63
ответ дан 22 November 2019 в 23:57
поделиться

В Linq-To-Sql

нет сокращений операторов. См. здесь .

Короче говоря, внутри условного предложения запроса Linq-To-Sql, вы не можете использовать условные ярлыки, такие как || и && , чтобы избежать исключений с нулевой ссылкой; Linq-To-Sql оценивает обе стороны оператора OR или AND, даже если первое условие избавляет от необходимости оценивать второе условие!

34
ответ дан 22 November 2019 в 23:57
поделиться

Перечисления можно оценивать более одного раза

Это укусит вас, когда у вас есть ленивый перечисляемый, и вы проводите над ним итерацию дважды и получаете разные результаты. (или вы получаете одни и те же результаты, но выполняете их дважды без необходимости)

Например, во время написания определенного теста мне понадобилось несколько временных файлов для проверки логики:

var files = Enumerable.Range(0, 5)
    .Select(i => Path.GetTempFileName());

foreach (var file in files)
    File.WriteAllText(file, "HELLO WORLD!");

/* ... many lines of codes later ... */

foreach (var file in files)
    File.Delete(file);

Представьте себе мое удивление, когда File.Delete(file) выбрасывает FileNotFound! Здесь происходит то, что файлы , перечисленные в списке, получали итерацию дважды (результаты первой итерации просто не запомнились) и на каждой новой итерации вы бы переименовывали Путь. GetTempFilename(), так что вы получите другой набор временных имен файлов.

Решение, конечно же, заключается в том, чтобы с нетерпением ожидать получения значения с помощью ToArray() или ToList():

var files = Enumerable.Range(0, 5)
    .Select(i => Path.GetTempFileName())
    .ToArray();

Это еще страшнее, когда вы делаете что-то многопоточное, например:

foreach (var file in files)
    content = content + File.ReadAllText(file);

и вы узнаете content.Length все равно 0 после всех записей!!!! Затем вы начинаете строго проверять, что у вас нет состояния гонки, когда.... после одного потраченного часа... вы выяснили, что это просто крошечная штучка Enumerable gotcha, которую вы забыли....

.
13
ответ дан 22 November 2019 в 23:57
поделиться

Окно наблюдения за Гейзенбергом

Это может сильно вас укусить, если вы выполняете загрузку по требованию, например:

private MyClass _myObj;
public MyClass MyObj {
  get {
    if (_myObj == null)
      _myObj = CreateMyObj(); // some other code to create my object
    return _myObj;
  }
}

А теперь давайте скажем, у вас есть код в другом месте, использующий это:

// blah
// blah
MyObj.DoStuff(); // Line 3
// blah

Теперь вы хотите отладить свой метод CreateMyObj () . Итак, вы ставите точку останова в строке 3 выше, чтобы войти в код. Для удобства вы также помещаете точку останова в строку выше, которая говорит _myObj = CreateMyObj (); , и даже точку останова внутри самого CreateMyObj () .

Код достигает точки останова в строке 3. Вы входите в код. Вы ожидаете ввести условный код, потому что _myObj , очевидно, имеет значение null, верно? Э ... так ... почему он пропустил условие и сразу перешел к return _myObj ?! Вы наводите указатель мыши на _myObj ...и действительно, это имеет значение! Как это случилось?!

Ответ заключается в том, что ваша среда IDE вызвала получение значения, потому что у вас открыто окно "просмотра" - особенно окно просмотра "Autos", в котором отображаются значения всех переменных / свойств, относящихся к текущей или предыдущей строке. исполнения. Когда вы достигли точки останова в строке 3, окно наблюдения решило, что вам будет интересно узнать значение MyObj , поэтому за кулисами, игнорируя любую из ваших точек останова , он пошел и вычислил для вас значение MyObj - , включая вызов CreateMyObj () , который устанавливает значение _myObj!

Вот почему я называю это окном наблюдения Гейзенберга - вы не можете наблюдать значение, не влияя на него ... :)

GOTCHA!


Изменить - я считаю, что комментарий @ ChristianHayter заслуживает включения в основной ответ, потому что он выглядит как эффективное решение этой проблемы. Поэтому каждый раз, когда у вас есть свойство с отложенной загрузкой ...

Украсьте свое свойство [DebuggerBrowsable (DebuggerBrowsableState.Never)] или [DebuggerDisplay ("<загружено по запросу>")]. - Кристиан Хейтер

193
ответ дан 22 November 2019 в 23:57
поделиться