If you aren't sure what a method returns, open Google and type in the name:
response.getresponsestream[
^]
Normally near the top, you will find the MSDN documentaion for the method:
System.Net.WebResponse.GetResponseStream[
^]
Which will give you full details about it, including the return type:
Return Value
Type: System.IO.Stream
An instance of the Stream class for reading data from the Internet resource.
"@OriginalGriff:ok i think ivé managed to understand a bit of this.stream class is an abstract class and the method getresponsestream() of the response class just create an instance of stream class and returns this instance to the stream class as return type and this is what usually happens when a class variable refers to some method of another class.what i am confused with is, how an instance of abstract class gets created since its illegal in c#."
OK... Let's see if I can explain...bear with me, this isn't easy without pictures or being able to see when your eyes start to glaze over...
You are right that you can't create an instance of an abstrct class - but you can create an instance of a class
derived from an abstract class:
public abstract class MyBase
{
public abstract void MyMethod();
}
public class MyClass : MyBase
{
public override void MyMethod() { }
}
If you declare these classes, in your form class you can happily say:
private void TryThis()
{
MyBase reference;
}
Or
private void TryThis()
{
MyClass reference;
}
And either will compile.
What you can't do is this:
private void TryThis()
{
MyBase reference = new MyBase();
}
because the compiler will (rightly) give you an error:
Error 1 Cannot create an instance of the abstract class or interface 'OneOffApp.frmMain.MyBase' C:\Users\griff\Documents\My Projects\OneOffApp\OneOffApp\frmMain.cs 167 32 OneOffApp
Because MyBase is abstract.
Which means abstract class variables (i.e. abstract class references) are pretty useless, right?
Well, no - actually they are very useful.
Assume you declare two derived classes:
public abstract class MyBase
{
public abstract string MyMethod();
}
public class MyClass1 : MyBase
{
public override string MyMethod() { return "MyClass1:MyMethod"; }
}
public class MyClass2 : MyBase
{
public override string MyMethod() { return "MyClass2:MyMethod"; }
}
If you then declare an variable of the base (abstract) class, you can assign an instance of either class to it:
private void TryThis()
{
MyBase reference;
reference = new MyClass1();
reference = new MyClass2();
}
And not only will the compiler not complain, you can call the methods of the abstract class and the system will sort out which actual method you wanted and call the appropriate one in the appropriate derived class:
private void TryThis()
{
MyBase reference;
reference = new MyClass1();
Console.WriteLine(reference.MyMethod());
reference = new MyClass2();
Console.WriteLine(reference.MyMethod());
}
Will print:
MyClass1:MyMethod
MyClass2:MyMethod
This is what is happening with your code: GetResponseStream is returning an instance of a class derived from the abstract Stream class. It could be a MemoryStream, a FileStream, an XMLStream (if they existed) - your code does not care. As long as the class instance that is returned is derived from the Stream class you can use all the methods of the Stream without knowing or caring what kind of stream it is. The system sorts that out for you.
This is good stuff! Why? Because it lets you write a method that works to a file (via a FileStream)
and without changing it your code can work to any class derived from Stream:
Microsoft.JScript.COMCharStream
System.Data.OracleClient.OracleBFile
System.Data.OracleClient.OracleLob
System.Data.SqlTypes.SqlFileStream
System.IO.BufferedStream
System.IO.Compression.DeflateStream
System.IO.Compression.GZipStream
System.IO.FileStream
System.IO.MemoryStream
System.IO.Pipes.PipeStream
System.IO.UnmanagedMemoryStream
System.Net.Security.AuthenticatedStream
System.Net.Sockets.NetworkStream
System.Printing.PrintQueueStream
System.Security.Cryptography.CryptoStream
Are the standard .NET ones. So your "file save" method can be saving in an encrypted file, or a ZIP archive without actually knowing anything about it. And it works.
This doesn't just apply to abstract classes either - this behaviour is "wired in" to the whole of .NET. Abstract classes just provide a "contract" with some predefined behaviours (unlike an Interface which only provides the "contract")
As long as the requirements of the contract are met, it gets sorted out for you, and "just works".
This makes code a lot more reliable - becuase you don't need to write the smae code for a file, a zip, to memory, to encrypted data, to ...
Did that make any sense? :laugh: