$album_and_photo_id = [string]$photos_array.owner_id[$i_photo] + "_" + [string]$photos_array.id[$i_photo]
$filename = $path + $album_and_photo_id + ".jpg" #формируем имя файла без лайков в метаданных
List - внутренне хранит массив и отслеживает логический размер списка и размер поддерживающего массива. Добавление элемента является либо простым случаем установки очередного значения в массиве, либо (если массив уже заполнен) копированием существующего содержимого в новый массив большего размера (обычно в два раза, т.е. происходит удвоение, но это недокументированно) и затем установки в нем значения. Сложность O(1) или O(n) в зависимости от того требуется ли копирование значений. Удаление элемента из List требует копирования расположенных за ним элементов на позицию назад, поэтому сложность составляет O(n-k), где k - индекс удаляемого элемента. По индексу RemoveAt() удалять значительно быстрее чем по значению Remove(), т.к. во втором случае происходит сравнение каждого элемента где бы он не находился сложность O(n).
**Массивы** - самый низкий уровень коллекций в .Net. Унаследованы от System.Array, и они единственные имеют прямую поддержку в среде CLR. Массивы всегда изменяемы в терминах своих элементов, но всегда фиксированы в терминах своих размеров.
Foreach для массива использует его свойство Length и индексатор массива, а не создает объект итератора.
**LinkedList** - связанный список, каждый элемент которого имеет ссылку на предыдущий и следующий элемент. Быстро можно удалять, вставлять новые элементы, т.к. происходит только изменение ссылок на соседних узлах. Проход по коллекции тоже эффективен, но разумеется нет индекса.
**Dictionary** - подобно List хранит свои элементы в массиве, со всеми вытекающими по вставке и увеличению размера последствиями. Для реализации эффективного поиска использует хештаблицу. Можно либо применять стандартные функции хеширования и эквивалентности внутри самих объектов ключей, либо передать реализацию IEqualityComparer в аргументе конструктора. Ключи должны быть уникальными, но хешкоды могут совпадать, что снижает эффективность поиска. Словарь даст отказ, если ключи являются изменяемыми и меняют свои хешкоды после того, как были вставлены в словарь. Внутри этого словаря нет гарантии порядка следования элементов, так что рассчитывать на него нельзя. Вставка происходит на основе ключа (что-то вроде индекса), а не последовательности заполнения словаря.
**ReadOnlyDictionary<,>** - просто оболочка, которая скрывает все изменяемые операции за явной реализацией интерфейса, и генерирует исключение если они все же вызываются. Но если лежащая в основе коллекция (та что передается конструктору) модифицируется, то модификации будут видны через оболочку.
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.CreateNoWindow = true;
//p.StartInfo.StandardOutputEncoding = System.Text.Encoding.UTF8;
int lcid = GetSystemDefaultLCID();
var ci = System.Globalization.CultureInfo.GetCultureInfo(lcid);
var page = ci.TextInfo.OEMCodePage;
p.StartInfo.StandardOutputEncoding = Encoding.GetEncoding(page);
p.Start();
try
{
p.BeginOutputReadLine();
p.BeginErrorReadLine();
p.StandardInput.AutoFlush = true;
p.OutputDataReceived += (s, e) => { ... }
p.ErrorDataReceived += (s, er) => { ... }
while (true)
{ // "\x3" - Ctrl+C
if (p.HasExited == true) { break; }
p.StandardInput.WriteLine( ... );
}
}
catch (Exception)
{
...
}
[ContractClass(typeof(IArrayContract))]
public interface IArray
{ контракт }
[ContractClassFor(typeof(IArray))]
internal abstract class IArrayContract : IArray
{ проверка входных и выходных параметров контрактов }
Глава 7. Метаданные и валидация модели
Аннотации данных для отображения свойств
Основы валидации
Атрибуты валидации
Валидация модели в контроллере
Отображение ошибок валидации
Создание собственной логики валидации
public class MovieViewModel : IValidatableObject
{
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Image { get; set; }
public string Genre { get; set; }
public int GenreId { get; set; }
public string Director { get; set; }
public string Writer { get; set; }
public string Producer { get; set; }
public DateTime ReleaseDate { get; set; }
public byte Rating { get; set; }
public string TrailerURI { get; set; }
public bool IsAvailable { get; set; }
public int NumberOfStocks { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var validator = new MovieViewModelValidator();
var result = validator.Validate(this);
return result.Errors.Select(item => new ValidationResult(item.ErrorMessage, new[] { item.PropertyName }));
}
}
public class MovieViewModelValidator : AbstractValidator<MovieViewModel>
{
public MovieViewModelValidator()
{
RuleFor(movie => movie.GenreId).GreaterThan(0)
.WithMessage("Select a Genre");
RuleFor(movie => movie.Director).NotEmpty().Length(1,100)
.WithMessage("Select a Director");
RuleFor(movie => movie.Writer).NotEmpty().Length(1,50)
.WithMessage("Select a writer");
RuleFor(movie => movie.Producer).NotEmpty().Length(1, 50)
.WithMessage("Select a producer");
RuleFor(movie => movie.Description).NotEmpty()
.WithMessage("Select a description");
RuleFor(movie => movie.Rating).InclusiveBetween((byte)0, (byte)5)
.WithMessage("Rating must be less than or equal to 5");
RuleFor(movie => movie.TrailerURI).NotEmpty().Must(ValidTrailerURI)
.WithMessage("Only Youtube Trailers are supported");
}
private bool ValidTrailerURI(string trailerURI)
{
return (!string.IsNullOrEmpty(trailerURI) && trailerURI.ToLower().StartsWith("https://www.youtube.com/watch?"));
}
}