Как DeflateStream.read перенаправляет на System.Net.ConnectStream.Read?

#c# #stream #gzipstream #deflatestream

#c# #поток #gzipstream #дефлатный поток

Вопрос:

В процессе отладки кода и мне кажется, что DeflateStream.read перенаправляет на System.Net.ConnectStream.Read? Когда я проверяю исходный код MSDN, я не мог легко найти это перенаправление. Кто-нибудь может помочь мне найти, как это происходит? Спасибо!

Ответ №1:

Потоки не «перенаправляются» — вместо этого используется DeflateStream.Read переносит метод чтения исходного потока.

То есть обертывающий DeflateStream передается исходному потоку (т. Е. В конструкторе), так что при вызове Read он считывает исходный поток (по крайней мере, в той мере, в какой он может выдавать допустимый вывод), а затем возвращает обработанный результат из своей собственной реализации Read 1 .

Из-за подтипов (и полиморфизма включения) любой объект, который соответствует (и является подтипом) IO.Stream, может быть предоставлен в качестве исходного потока. Что касается кода DeflateStream, это гарантирует, что обернутый _stream имеет подходящий метод чтения.

Фактический объект stream, предоставляемый конструктору, может быть реализован как FileStream, MemoryStream, ResourceStream, ConnectedStream и т. Д.

Дополнительные сведения см. в разделе Полиморфизм (руководство по программированию на C #) и полиморфизм в .NET — CodeProject (раздел о полиморфизме во время выполнения).


1 Из источника, найденного здесь, видно, что это составляет:

 public override int Read(byte[] array, int offset, int count) {
    // Setup state

    while(true) {
        // Process buffer into result until..
        bytesRead = inflater.Inflate(array, currentOffset, remainingCount);
        if(remainingCount == 0) {
          // ..read enough, break
        }
        if (inflater.Finished()) {
          // ..or end of source stream, break
        }
        // Making sure to read more from the source stream as required
        // (_stream is a Stream, assigned in the constructor)
        int bytes = _stream.Read( buffer, 0, buffer.Length);
        inflater.SetInput(buffer, 0 , bytes);
    }

    // ..
}
 

Комментарии:

1. Спасибо — но _stream определяется как System.IO.Stream, а не как System.Net.ConnectedStream, поэтому я все еще не совсем понимаю, как код попадает в ConnectedStream.read…

2. Я вижу — так в основном и есть . NET не навязывает здесь ConnectionStream, а скорее код, который я читаю, создает объект DeflateStream с использованием ConnectStream? Я думал, что DeflatStream.read всегда вызывает ConnectSteam.read, и это реализовано .NET

3. @user2210021 правильно. Для .NET требуется только «поток», и он будет работать до тех пор, пока фактический переданный объект является соответствующей реализацией. «Фактический» метод чтения будет вызываться во время выполнения из-за полиморфизма подтипов (поскольку метод чтения является виртуальным). Я добавил несколько ссылок.