日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C#基礎--特殊的集合

作者:sufengmarket 更新時間: 2022-09-25 編程語言

文章目錄

  • 特殊的集合
    • BitArray 類
    • BitVector32 結構
    • 可觀察的集合
    • 不變的集合
    • 并發集合

特殊的集合

BitArray 類

BitArray類是一個引用類型,它包含一個int數組,其中每32位使用一個新整數。
在這里插入圖片描述

public static class BitArrayExtensions
{
    public static string GetBitsFormat(this BitArray bits)
    {
        var sb = new StringBuilder();
        for (int i = bits.Length - 1; i >= 0; i--)
        {
            sb.Append(bits[i] ? 1 : 0);
            if (i != 0 && i % 4 == 0)
            {
                sb.Append("_");
            }
        }

        return sb.ToString();
    }
}

class Program
{
    static void Main()
    {
        var bits1 = new BitArray(9);
        bits1.SetAll(true);
        bits1.Set(1, false);
        bits1[5] = false;
        bits1[7] = false;
        Console.Write("initialized: ");
        Console.WriteLine(bits1.GetBitsFormat());

        Console.Write("not ");
        Console.Write(bits1.GetBitsFormat());
        bits1.Not();
        Console.Write(" = ");
        Console.WriteLine(bits1.GetBitsFormat());

        var bits2 = new BitArray(bits1);
        bits2[0] = true;
        bits2[1] = false;
        bits2[4] = true;
        Console.Write($"{bits1.GetBitsFormat()} OR {bits2.GetBitsFormat()}");
        Console.Write(" = ");
        bits1.Or(bits2);
        Console.WriteLine(bits1.GetBitsFormat());

        Console.Write($"{bits2.GetBitsFormat()} AND {bits1.GetBitsFormat()}");
        Console.Write(" = ");
        bits2.And(bits1);
        Console.WriteLine(bits2.GetBitsFormat());

        Console.Write($"{bits1.GetBitsFormat()} XOR {bits2.GetBitsFormat()}");
        bits1.Xor(bits2);
        Console.Write(" = ");
        Console.WriteLine(bits1.GetBitsFormat());

        Console.ReadLine();
    }
}

BitVector32 結構

如果事先知道需要的位數,就可以使用BitVector32結構替代BitArray類。BitVector32結構效率較高,因為 它是一個值類型,在整數棧上存儲位。一個整數可以存儲32位。如果需要更多的位,就可以使用多個BitVector32 值或BitArray類。BitArray類可以根據需要增大,但BitVector32結構不能。
在這里插入圖片描述

public static class BinaryExtensions
{
    public static string AddSeparators(this string number) =>
        number.Length <= 4 ? number :
            string.Join("_",
                Enumerable.Range(0, number.Length / 4)
                    .Select(i => number.Substring(startIndex: i * 4, length: 4)).ToArray());

    public static string ToBinaryString(this int number) =>
        Convert.ToString(number, toBase: 2).AddSeparators();
}


class Program
{
    static void Main()
    {
        // create a mask using the CreateMask method
        var bits1 = new BitVector32();
        int bit1 = BitVector32.CreateMask();
        int bit2 = BitVector32.CreateMask(bit1);
        int bit3 = BitVector32.CreateMask(bit2);
        int bit4 = BitVector32.CreateMask(bit3);
        int bit5 = BitVector32.CreateMask(bit4);

        bits1[bit1] = true;
        bits1[bit2] = false;
        bits1[bit3] = true;
        bits1[bit4] = true;
        bits1[bit5] = true;
        Console.WriteLine(bits1);

        // create a mask using an indexer
        bits1[0xab_cdef] = true;
        Console.WriteLine();

        int received = 0x79ab_cdef;

        BitVector32 bits2 = new BitVector32(received);
        Console.WriteLine(bits2);

        // sections: FF EEE DDD CCCC BBBBBBBB
        // AAAAAAAAAAAA
        BitVector32.Section sectionA = BitVector32.CreateSection(0xfff);
        BitVector32.Section sectionB = BitVector32.CreateSection(0xff, sectionA);
        BitVector32.Section sectionC = BitVector32.CreateSection(0xf, sectionB);
        BitVector32.Section sectionD = BitVector32.CreateSection(0x7, sectionC);
        BitVector32.Section sectionE = BitVector32.CreateSection(0x7, sectionD);
        BitVector32.Section sectionF = BitVector32.CreateSection(0x3, sectionE);

        Console.WriteLine($"Section A: {bits2[sectionA].ToBinaryString()}");
        Console.WriteLine($"Section B: {bits2[sectionB].ToBinaryString()}");
        Console.WriteLine($"Section C: {bits2[sectionC].ToBinaryString()}");
        Console.WriteLine($"Section D: {bits2[sectionD].ToBinaryString()}");
        Console.WriteLine($"Section E: {bits2[sectionE].ToBinaryString()}");
        Console.WriteLine($"Section F: {bits2[sectionF].ToBinaryString()}");

        Console.ReadLine();
    }
}

可觀察的集合

如果需要集合中的元素何時刪除或添加的信息,就可以使用ObservableCollectionO類。這個類最初是為
WPF定義的,這樣UI就可以得知集合的變化,通用Windows應用程序使用它的方式相同。這個類的名稱空間 是System.Collections. ObjectModeloObservableCollection類派生自Collection基類,該基類可用于創建自定義集合,并在內部使用Ust 類。重寫基類中的虛方法SetltonO和RemoveltonO*以觸發CollectionChanged事件。這個類的用戶可以使用 INotifyCollectionChanged 接口注冊這個事件。

class Program
{
    static void Main()
    {
        var data = new ObservableCollection<string>();
        
        data.CollectionChanged += Data_CollectionChanged;
        data.Add("One");
        data.Add("Two");
        data.Insert(1, "Three");
        data.Remove("One");

        data.CollectionChanged -= Data_CollectionChanged;

        Console.ReadLine();
    }

    public static void Data_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        Console.WriteLine($"action: {e.Action.ToString()}");

        if (e.OldItems != null)
        {
            Console.WriteLine($"starting index for old item(s): {e.OldStartingIndex}");
            Console.WriteLine("old item(s):");
            foreach (var item in e.OldItems)
            {
                Console.WriteLine(item);
            }
        }
        if (e.NewItems != null)
        {
            Console.WriteLine($"starting index for new item(s): {e.NewStartingIndex}");
            Console.WriteLine("new item(s): ");
            foreach (var item in e.NewItems)
            {
                Console.WriteLine(item);
            }
        }
        Console.WriteLine();
    }
}

不變的集合

如果對象可以改變其狀態,就很難在多個同時運行的任務中使用。這些集合必須同步。如果對象不能改變 其狀態,就很容易在多個線程中使用。不能改變的對象稱為不變的對象。不能改變的集合稱為不變的集合。

public class Account
{
    public Account(string name, decimal amount)
    {
        Name = name;
        Amount = amount;
    }
    public string Name { get; }
    public decimal Amount { get; }
}

class Program
{
    static void Main()
    {
        SimpleArrayDemo();
        ImmutableList<Account> accounts = CreateImmutableList();
        UsingABuilder(accounts);
        LinqDemo();

        Console.ReadLine();
    }

    public static void LinqDemo()
    {
        ImmutableArray<string> arr = ImmutableArray.Create<string>("one", "two", "three", "four", "five");
        var result = arr.Where(s => s.StartsWith("t"));
    }

    public static void UsingABuilder(ImmutableList<Account> immutableAccounts)
    {
        ImmutableList<Account>.Builder builder = immutableAccounts.ToBuilder();
        for (int i = 0; i < builder.Count; i++)
        {
            Account a = builder[i];
            if (a.Amount > 0)
            {
                builder.Remove(a);
            }
        }

        ImmutableList<Account> overdrawnAccounts = builder.ToImmutable();

        overdrawnAccounts.ForEach(a => Console.WriteLine($"{a.Name} {a.Amount}"));
    }

    public static ImmutableList<Account> CreateImmutableList()
    {
        var accounts = new List<Account>() {
            new Account("Scrooge McDuck", 667377678765m),
            new Account("Donald Duck", -200m),
            new Account("Ludwig von Drake", 20000m)
        };

        ImmutableList<Account> immutableAccounts = accounts.ToImmutableList();

        foreach (var account in immutableAccounts)
        {
            Console.WriteLine($"{account.Name} {account.Amount}");
        }

        immutableAccounts.ForEach(a => Console.WriteLine($"{a.Name} {a.Amount}"));

        return immutableAccounts;
    }

    public static void SimpleArrayDemo()
    {
        ImmutableArray<string> a1 = ImmutableArray.Create<string>();
        ImmutableArray<string> a2 = a1.Add("Williams");
        ImmutableArray<string> a3 =
            a2.Add("Ferrari").Add("Mercedes").Add("Red Bull Racing");
    }
}

并發集合

不變的集合很容易在多個線程中使用,因為它們不能改變。如果希望使用應在多個線程中改變的集合,.NET 在名稱空間System.Collections.Concurrent中提供了幾個線程安全的集合類。線程安全的集合可防止多個線程以 相互沖突的方式訪問集合。
為了對集合進行線程安全的訪問,定義了 IProducerConsumerCollection接口。這個接口中最重要的方法是 TryAdd()和TryTake()。TryAdd()方法嘗試給集合添加一項,但如果集合禁止添加項,這個操作就可能失敗。為了給 出相關信息,TiyAdd()方法返回一個布爾值,以說明操作是成功還是失敗。TryTake()方法也以這種方式工作,以通 知調用者操作是成功還是失敗,并在操作成功時返回集合中的項。

public class ColoredConsole
{
    private static object syncOutput = new object();
    public static void WriteLine(string message)
    {
        lock (syncOutput)
        {
            Console.WriteLine(message);
        }
    }
    public static void WriteLine(string message, string color)
    {
        lock (syncOutput)
        {
            Console.ForegroundColor = (ConsoleColor)Enum.Parse(
                typeof(ConsoleColor), color);
            Console.WriteLine(message);
            Console.ResetColor();
        }
    }
}

public class Info
{
    public Info(string word, int count)
    {
        Word = word;
        Count = count;
    }

    public string Word { get; }
    public int Count { get; }
    public string Color { get; set; }

    public override string ToString() => $"{Count} times: {Word}";
}

public static class PipelineStages
{
    public static Task ReadFilenamesAsync(string path, BlockingCollection<string> output)
    {
        return Task.Factory.StartNew(() =>
        {
            foreach (string filename in Directory.EnumerateFiles(path, "*.cs",
                SearchOption.AllDirectories))
            {
                output.Add(filename);
                ColoredConsole.WriteLine($"stage 1: added {filename}");
            }
            output.CompleteAdding();
        }, TaskCreationOptions.LongRunning);
    }

    public static async Task LoadContentAsync(BlockingCollection<string> input, BlockingCollection<string> output)
    {
        foreach (var filename in input.GetConsumingEnumerable())
        {
            using (FileStream stream = File.OpenRead(filename))
            {
                var reader = new StreamReader(stream);
                string line = null;
                while ((line = await reader.ReadLineAsync()) != null)
                {
                    output.Add(line);
                    ColoredConsole.WriteLine($"stage 2: added {line}");
                    await Task.Delay(20);
                }
            }
        }
        output.CompleteAdding();
    }

    public static Task ProcessContentAsync(BlockingCollection<string> input,  ConcurrentDictionary<string, int> output)
    {
        return Task.Factory.StartNew(() =>
        {
            foreach (var line in input.GetConsumingEnumerable())
            {
                string[] words = line.Split(' ', ';', '\t', '{', '}', '(', ')',
                    ':', ',', '"');
                foreach (var word in words.Where(w => !string.IsNullOrEmpty(w)))
                {
                    output.AddOrUpdate(key: word, addValue: 1, updateValueFactory: (s, i) => ++i);
                    ColoredConsole.WriteLine($"stage 3: added {word}");
                }
            }
        }, TaskCreationOptions.LongRunning);
    }

    public static Task TransferContentAsync(ConcurrentDictionary<string, int> input, BlockingCollection<Info> output)
    {
        return Task.Factory.StartNew(() =>
        {
            foreach (var word in input.Keys)
            {
                if (input.TryGetValue(word, out int value))
                {
                    var info = new Info(word, value);
                    output.Add(info);
                    ColoredConsole.WriteLine($"stage 4: added {info}");
                }
            }
            output.CompleteAdding();
        }, TaskCreationOptions.LongRunning);
    }

    public static Task AddColorAsync(BlockingCollection<Info> input, BlockingCollection<Info> output)
    {
        return Task.Factory.StartNew(() =>
        {
            foreach (var item in input.GetConsumingEnumerable())
            {
                if (item.Count > 40)
                {
                    item.Color = "Red";
                }
                else if (item.Count > 20)
                {
                    item.Color = "Yellow";
                }
                else
                {
                    item.Color = "Green";
                }
                output.Add(item);
                ColoredConsole.WriteLine($"stage 5: added color {item.Color} to {item}");
            }
            output.CompleteAdding();
        }, TaskCreationOptions.LongRunning);
    }

    public static Task ShowContentAsync(BlockingCollection<Info> input)
    {
        return Task.Factory.StartNew(() =>
        {
            foreach (var item in input.GetConsumingEnumerable())
            {
                ColoredConsole.WriteLine($"stage 6: {item}", item.Color);
            }
        }, TaskCreationOptions.LongRunning);
    }
}
class Program
{
    static void Main()
    {
        StartPipelineAsync().Wait();
        Console.ReadLine();
    }

    public static async Task StartPipelineAsync()
    {
        var fileNames = new BlockingCollection<string>();
        var lines = new BlockingCollection<string>();
        var words = new ConcurrentDictionary<string, int>();
        var items = new BlockingCollection<Info>();
        var coloredItems = new BlockingCollection<Info>();
        Task t1 = PipelineStages.ReadFilenamesAsync(@"../..", fileNames);
        ColoredConsole.WriteLine("started stage 1");
        Task t2 = PipelineStages.LoadContentAsync(fileNames, lines);
        ColoredConsole.WriteLine("started stage 2");
        Task t3 = PipelineStages.ProcessContentAsync(lines, words);
        await Task.WhenAll(t1, t2, t3);
        ColoredConsole.WriteLine("stages 1, 2, 3 completed");
        Task t4 = PipelineStages.TransferContentAsync(words, items);
        Task t5 = PipelineStages.AddColorAsync(items, coloredItems);
        Task t6 = PipelineStages.ShowContentAsync(coloredItems);
        ColoredConsole.WriteLine("stages 4, 5, 6 started");

        await Task.WhenAll(t4, t5, t6);
        ColoredConsole.WriteLine("all stages finished");
    }
}

原文鏈接:https://blog.csdn.net/huan13479195089/article/details/127033890

欄目分類
最近更新