1

I am following the example here (How to attach a file to work item in TFS without physical file path?) to attach a file to a work item in TFS, by having a stream instead of having a physical file. I have the following code:

internal static void AddAttachment(WorkItemServer server, Project teamProject, string fileContent, WorkItem workItem)
{
    FileAttachment attachment = new FileAttachment();
    using (MemoryStream stream = new MemoryStream())
    {
        using (StreamWriter writer = new StreamWriter(stream))
        {
            writer.Write(fileContent);
            writer.Flush();
            stream.Position = 0;

            attachment.LocalFile = stream;
            attachment.AreaNodeUri = "";
            attachment.FileNameGUID = Guid.NewGuid();
            attachment.ProjectUri = teamProject.Uri.ToString();

            server.UploadFile(attachment);

            const string c_UpdatePackage = @"<validxml>";
            XmlDocument updatePackage = new XmlDocument();
            updatePackage.LoadXml(string.Format(c_UpdatePackage, workItem.Id /*work item ID*/, workItem.Rev /*work item latest revision*/, "Test attachment", attachment.FileNameGUID, DateTime.Now.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff'Z'"), fileContent.Length, "John Smith", "http://localhost:8080/tfs/defaultcollection"));

            XmlElement outputPackage;
            string dbStamp;
            IMetadataRowSets metadata;
            server.Update(Guid.NewGuid().ToString(), updatePackage.DocumentElement, out outputPackage, null, out dbStamp, out metadata);
        }
    }
}

My question: During the assignment

attachment.LocalFile = stream;

Is stream copied to attachment.LocalFile by reference or by value? If it is copied by reference, I think the above code will not have a memory leak since it is disposing the stream in using:

using (MemoryStream stream = new MemoryStream()) { ... }

But if it copied by value(a copy of stream is made), this would leave a memory leak since FileAttachment is not being disposed, right? If memory leak is present, I think it is not possible to fix this memory leak since FileAttachment is not inheriting IDisposable. Below is the decompiled code resharper shows for FileAttachment:

namespace Microsoft.TeamFoundation.WorkItemTracking.Proxy
{
    public struct FileAttachment
    {
        private Stream m_localFile;
        ...
        public Stream LocalFile
        {
            get
            {
                return this.m_localFile;
            }
            set
            {
                this.m_localFile = value;
            }
        }
    }
 }

How can we confirm whether the stream object is being copied by reference or by value? If it is copied by value, how can we stop the memory leak?

1
  • Objects are always copied by reference. Primitive types are copied by value. That's how you know. Commented Apr 26, 2016 at 2:13

1 Answer 1

0

An object is a reference type if it is a class, and a value type if it is a struct or enumerable. FileAttachment is a class.

As such, the assignment attachment.LocalFile = stream; does not result in a memory leak because it is a copy by reference assignment.

It should also be noted that the attachment.LocalFile property, once it exits that using() scope, will point to invalid data, and will throw an exception if anything attempts to access that property.

Sign up to request clarification or add additional context in comments.

3 Comments

I verified that the stream is not readable once I exit the using() scope. But just one issue. You mentioned in your answer that FileAttachment is a class. But actually it is a struct. Does this change the behavior of FileAttachment.LocalFile?
I'm guessing you are rolling your own FileAttachment class? W/r/t it being a struct, it shouldn't change anything. A reference type contained within a struct will behave as any reference type usually does. Look at stackoverflow.com/a/945708/6137718 . Mutable fields within a struct is usually considered bad practice, though.
The FileAttachment class is coming from Microsoft.TeamFoundation.WorkItemTracking.Proxy dll.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.