Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IDisposable objects as ref param to method

Tags:

c#

I was doing a refactoring of class and thought of moving 100 lines in a separate method. Like this:

using iTextSharp.text;
using iTextSharp.text.pdf;

 class Program
{
    private static void Main(string[] args)
    {
        Document doc = new Document(iTextSharp.text.PageSize.LETTER, 10, 10, 42, 35);
        using (var mem = new MemoryStream())
        {
            using (PdfWriter wri = PdfWriter.GetInstance(doc, mem))
            {
                doc.Open();
                AddContent(ref doc, ref wri);
                doc.Close();
                File.WriteAllBytes(@"C:\testpdf.pdf", mem.ToArray());
            }
        }
    }

    public static void AddContent(ref Document doc, ref PdfWriter writer)
    {
        var header = new Paragraph("My Document") { Alignment = Element.ALIGN_CENTER };
        var paragraph = new Paragraph("Testing the iText pdf.");
        var phrase = new Phrase("This is a phrase but testing some formatting also. \nNew line here.");
        var chunk = new Chunk("This is a chunk.");
        doc.Add(header);
        doc.Add(paragraph);
        doc.Add(phrase);
        doc.Add(chunk);

    }
}

At calling method of Compiler throws exception : Readonly local variable cannot be used as an assignment target for doc and mem.

Edit: here only i adding content in pdf document in another method. so i need to pass same doc object, right ? so why can't i use ref or out param.

Technically using defies the purpose of ref param here.

Tried to look on MSDN:

A ReadOnly property has been found in a context that assigns a value to it. 
Only writable variables, properties, and array elements can have values assigned
to them during execution.

How the objects become read only at calling of Method? Within the scope object is alive and you can do whatever you want.

like image 792
joshua Avatar asked Dec 18 '13 10:12

joshua


People also ask

What is IDisposable object in c#?

IDisposable is an interface that contains a single method, Dispose(), for releasing unmanaged resources, like files, streams, database connections and so on.

Why we use IDisposable in c#?

IDisposable is an interface that contains only a single method i.e. Dispose(), for releasing unmanaged resources. IDisposable is defined in the System namespace. It provides a mechanism for releasing unmanaged resources.

Is StreamReader IDisposable?

Classes such as Stream , StreamReader , StreamWriter etc implements IDisposable interface.

How does IDisposable work?

In a nutshell, an IDisposable class allows you to explicitly handle the deallocation of resources (typically unmanaged resources or database connections) via the Dispose() method. IDisposable class instances should be created within a "Using" block so as to ensure that the Dispose method is actually called.


2 Answers

This is because you declare doc and mem using the using keyword. Citing MSDN:

Within the using block, the object is read-only and cannot be modified or reassigned.

Hence you get the error about the read-only variable.


If you still want to pass parameters by reference, you can use try ... finally block instead of using. As pointed out by Jon Skeet, this code is similar to how using is expanded but with a using statement, it's always the original object which is disposed. In the code below, if AddContent changes the value of doc, it will be that later value which is used in the Dispose call.

var doc = new Document(PageSize.A4, 5f, 5f, 5f, 5f);
try
{
     var mem = new MemoryStream();
     try
     {
         PdfWriter wri = PdfWriter.GetInstance(doc, output);
         doc.Open();
         AddContent(ref doc,ref wri );
         doc.Close();
     }
     finally
     {
         if (mem != null)
             ((IDisposable)mem).Dispose();
     }
 }
 finally
 {
     if (doc != null)
         ((IDisposable)doc).Dispose();
 }
 return output.ToArray();
like image 61
Szymon Avatar answered Oct 11 '22 14:10

Szymon


the mem variable is readonly, because of the using keyword. How should the compiler know otherwise what he has to dispose when leaving the using-scope when you override it's reference to the variable.

But why do you have to use the ref keyword anyway? In my opinion you do not need a ref.

like image 27
Herm Avatar answered Oct 11 '22 13:10

Herm