Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Document opening/saving idiom

Document opening/saving idiom

Scheduled Pinned Locked Moved C#
csharpc++tutorialquestion
5 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • O Offline
    O Offline
    Orjan Westin
    wrote on last edited by
    #1

    Coming from a C++ background, I'm keen to learn the C# idiom. Picking up the language is simple enough, and I'm finding my way around the class library, but I'm not familiar with the idiom, or "how things are done". I would like the code I write to follow the conventions well enough that an experienced C# developer reading the code can see what's going on without getting confused about alien idioms. (One example I've noticed is the use of foreach rather than for loops over collections.) Now, I have a document class for a desktop application, and I'd write its IO interface like this:

    class Document
    {
    // Default constructor (eg File->New)
    public Document()
    {}
    // Construct by reading from file (eg File->Open)
    public Document(string path)
    {}
    // Write document to path it opened from (eg File->Save, after opened or saved once)
    public void Write()
    {}
    // Write document to new path (eg File->Save As, of first File->Save after default construction)
    public void Write(string path)
    {}
    }

    I don't think this is idiomatic C# though. Most examples seem to pass in streams instead of path names, for instance, and handle that aspect (eg opening and closing IO streams) outside the document class, in the application. Is that correct? Should I write a separate serializer? Please let me know what the "proper" C# way of doing things like this is. Cheers, Orjan

    P P L OriginalGriffO 4 Replies Last reply
    0
    • O Orjan Westin

      Coming from a C++ background, I'm keen to learn the C# idiom. Picking up the language is simple enough, and I'm finding my way around the class library, but I'm not familiar with the idiom, or "how things are done". I would like the code I write to follow the conventions well enough that an experienced C# developer reading the code can see what's going on without getting confused about alien idioms. (One example I've noticed is the use of foreach rather than for loops over collections.) Now, I have a document class for a desktop application, and I'd write its IO interface like this:

      class Document
      {
      // Default constructor (eg File->New)
      public Document()
      {}
      // Construct by reading from file (eg File->Open)
      public Document(string path)
      {}
      // Write document to path it opened from (eg File->Save, after opened or saved once)
      public void Write()
      {}
      // Write document to new path (eg File->Save As, of first File->Save after default construction)
      public void Write(string path)
      {}
      }

      I don't think this is idiomatic C# though. Most examples seem to pass in streams instead of path names, for instance, and handle that aspect (eg opening and closing IO streams) outside the document class, in the application. Is that correct? Should I write a separate serializer? Please let me know what the "proper" C# way of doing things like this is. Cheers, Orjan

      P Offline
      P Offline
      Pete OHanlon
      wrote on last edited by
      #2

      I really wish I wasn't typing this on my phone because this is a fascinating question. Unfortunately I will have to give the shorthand version. The reason for using a stream rather than a path lies in OOP principles. Basically it's down to single responsibility The reasoning of it is this, your class shouldn't have to have different methods to serialise to different locations, so using a stream means that you can save to memory, or isolated storage or a standard file path, all with the same code. Saying that, it is common to provide a method that accepts a path which instantiates a stream and then calls the relevant override.

      *pre-emptive celebratory nipple tassle jiggle* - Sean Ewington

      "Mind bleach! Send me mind bleach!" - Nagy Vilmos

      CodeStash - Online Snippet Management | My blog | MoXAML PowerToys | Mole 2010 - debugging made easier

      1 Reply Last reply
      0
      • O Orjan Westin

        Coming from a C++ background, I'm keen to learn the C# idiom. Picking up the language is simple enough, and I'm finding my way around the class library, but I'm not familiar with the idiom, or "how things are done". I would like the code I write to follow the conventions well enough that an experienced C# developer reading the code can see what's going on without getting confused about alien idioms. (One example I've noticed is the use of foreach rather than for loops over collections.) Now, I have a document class for a desktop application, and I'd write its IO interface like this:

        class Document
        {
        // Default constructor (eg File->New)
        public Document()
        {}
        // Construct by reading from file (eg File->Open)
        public Document(string path)
        {}
        // Write document to path it opened from (eg File->Save, after opened or saved once)
        public void Write()
        {}
        // Write document to new path (eg File->Save As, of first File->Save after default construction)
        public void Write(string path)
        {}
        }

        I don't think this is idiomatic C# though. Most examples seem to pass in streams instead of path names, for instance, and handle that aspect (eg opening and closing IO streams) outside the document class, in the application. Is that correct? Should I write a separate serializer? Please let me know what the "proper" C# way of doing things like this is. Cheers, Orjan

        P Offline
        P Offline
        PIEBALDconsult
        wrote on last edited by
        #3

        I think what Pete alludes to is what I was going to say -- I would likely write several overloaded methods, depending on the situation: 0) One that takes a TextWriter and does the actual writing 1) One that takes a Stream, wraps it in a TextWriter, and passes it to 0 2) One that takes a FileInfo, opens a Stream for it, and passes it to 1 3) One that takes a string, wraps it in a FileInfo, and passes it to 2 A downside to this is that it adds a bunch of method calls and each method will likely perform its own parameter validation (null checking).

        1 Reply Last reply
        0
        • O Orjan Westin

          Coming from a C++ background, I'm keen to learn the C# idiom. Picking up the language is simple enough, and I'm finding my way around the class library, but I'm not familiar with the idiom, or "how things are done". I would like the code I write to follow the conventions well enough that an experienced C# developer reading the code can see what's going on without getting confused about alien idioms. (One example I've noticed is the use of foreach rather than for loops over collections.) Now, I have a document class for a desktop application, and I'd write its IO interface like this:

          class Document
          {
          // Default constructor (eg File->New)
          public Document()
          {}
          // Construct by reading from file (eg File->Open)
          public Document(string path)
          {}
          // Write document to path it opened from (eg File->Save, after opened or saved once)
          public void Write()
          {}
          // Write document to new path (eg File->Save As, of first File->Save after default construction)
          public void Write(string path)
          {}
          }

          I don't think this is idiomatic C# though. Most examples seem to pass in streams instead of path names, for instance, and handle that aspect (eg opening and closing IO streams) outside the document class, in the application. Is that correct? Should I write a separate serializer? Please let me know what the "proper" C# way of doing things like this is. Cheers, Orjan

          L Offline
          L Offline
          Lost User
          wrote on last edited by
          #4

          A stream is a wrapper around an array of bits. A file's location is a property of a file. Superfluous to mention; a MemoryStream doesn't have a filename, and neither does a NetworkStream. The class that you're describing does not only contain the contents of a file, but also holds the most common operations on that file from your application. I'd go for one constructor (due to KISS) until you actually need a second one. How you read the contents of the file is up to you, and how you make it's contents available too. ..but yes, I'd expect those methods to work internally with streams and a reader.

          Bastard Programmer from Hell :suss:

          1 Reply Last reply
          0
          • O Orjan Westin

            Coming from a C++ background, I'm keen to learn the C# idiom. Picking up the language is simple enough, and I'm finding my way around the class library, but I'm not familiar with the idiom, or "how things are done". I would like the code I write to follow the conventions well enough that an experienced C# developer reading the code can see what's going on without getting confused about alien idioms. (One example I've noticed is the use of foreach rather than for loops over collections.) Now, I have a document class for a desktop application, and I'd write its IO interface like this:

            class Document
            {
            // Default constructor (eg File->New)
            public Document()
            {}
            // Construct by reading from file (eg File->Open)
            public Document(string path)
            {}
            // Write document to path it opened from (eg File->Save, after opened or saved once)
            public void Write()
            {}
            // Write document to new path (eg File->Save As, of first File->Save after default construction)
            public void Write(string path)
            {}
            }

            I don't think this is idiomatic C# though. Most examples seem to pass in streams instead of path names, for instance, and handle that aspect (eg opening and closing IO streams) outside the document class, in the application. Is that correct? Should I write a separate serializer? Please let me know what the "proper" C# way of doing things like this is. Cheers, Orjan

            OriginalGriffO Offline
            OriginalGriffO Offline
            OriginalGriff
            wrote on last edited by
            #5

            Yes, a stream would be more normal, although as the others have said, a file path option doesn't hurt. One of the big strengths of passing a stream rather than a file is that the stream can be encapsulated in the containing class to form a compound document. If you think of your document as an excel sheet, then passing streams enables the excel file to contain a number of encapsulated sheets without your document being aware of it - you can't easily do that with files. Certainly, I would make the commitment to output to file at the highest level I can - if only so that I can easily reuse the lower level components. foreach is a very, very useful construct: it can't replace a for loop, but it builds on it:* If you do not need to know the position of an element in a collection, using a foreach loop makes the code cleaner and easier to read - you aren't creating simple variables unnecessarily.

            • If you do not want the collection to change while you go though it, the a foreach is much better - any attempt to add or remove elements will cause a run time error immediately, rather than waiting until something goes out of range.
              One of the hardest differences to get used to between C++ and C# is variable naming: gone is Hungarian notation, gone is m_blahblah, g_balhblah, and so forth! I've been using C# almost exclusively for a nuymber of years and I still call Buttons butOK and TextBoxes tbUserName! :laugh:

            Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water

            "I have no idea what I did, but I'm taking full credit for it." - ThisOldTony
            "Common sense is so rare these days, it should be classified as a super power" - Random T-shirt

            1 Reply Last reply
            0
            Reply
            • Reply as topic
            Log in to reply
            • Oldest to Newest
            • Newest to Oldest
            • Most Votes


            • Login

            • Don't have an account? Register

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • World
            • Users
            • Groups