|
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
{
public Document()
{}
public Document(string path)
{}
public void Write()
{}
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
|
|
|
|
|
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.
|
|
|
|
|
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).
|
|
|
|
|
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
|
|
|
|
|
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!
Ideological Purity is no substitute for being able to stick your thumb down a pipe to stop the water
|
|
|
|
|
Hello all,
I am making a project to finish my subject but I have some problem with the code of program. I am coding a code editor like Notepad++ for C#. I find any help in forum, but I have a problem that I can't find the help.
Well... Someone help me...
I want the code in a funtion or a region can expand and collapse like Nodepad++.
Can you guide me? Can you give the code demo?
Please give me the help to email: nguyenquangsang24@gmail.com
Thank very much.
|
|
|
|
|
|
|
I have a class that has a list of objects.
Since it doesn´t seem to work with xmlSerializer I´m trying to save to a binaryfile instead.
When I use BinaryReader I read a string using ReadString but can I read a List or an object?
|
|
|
|
|
Fisrt off, you should easily be able to serialise a List with XMLSerializer, you just need to ensure that Your custom class is marked with the XmlRoot attribute, and you create a class that inherits from List that holds your collection, something like this
[XmlRoot("Persons")]
public class People : List<Person>
{
}
[XmlRoot("Person")]
public class Person
{
public Person()
{
}
public Person(string name)
{
Name = name;
}
[XmlElement("Name")]
public string Name { get; set; }
}
then you can use this
using (StringWriter writer = new StringWriter())
{
XmlSerializer serializer = new XmlSerializer(typeof(Persons));
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);
XmlWriter xmlWriter = XmlWriter.Create(writer, settings);
serializer.Serialize(xmlWriter, personList, namespaces);
}
or something to that effect, and this should work to serialize to XML.
If you still want to serialize to a binary file, you should use a BinaryFormatter like this
using (Stream stream = File.Open("people.bin", FileMode.Create))
{
BinaryFormatter bin = new BinaryFormatter();
bin.Serialize(stream, People);
}
and deserialise also using a BinaryFormatter
using (Stream stream = File.Open("people.bin", FileMode.Open))
{
BinaryFormatter bin = new BinaryFormatter();
var people = (List<Person>)bin.Deserialize(stream);
}
Hope this helps
When I was a coder, we worked on algorithms. Today, we memorize APIs for countless libraries — those libraries have the algorithms - Eric Allman
|
|
|
|
|
We have created a window service in c# and in VS 2005 and when we ran that service on local server which is windows 2003 and SQL Server 2005 (both installed on same server ), the window service ran fine and updated the SQL Server database absolutely fine.
But when we are going live , we have the SQL Server 2005 on a remote database and remote connections are allowed in that (as when I am opening the through sql server management studio where window service will be installed ,its working fine). And I have installed the window service on Windows 2008 R2 Server and installation was fine .
But now the service is not updating our database SQL Server 2005 which is at remote locations. Also we are not sure , where should we what the error is.
I have seen in sql server 2005 properties that Allow Remote Connections to this Server is checked and remote query timeout is set at 600 seconds. And also if to Advanced section of properties , then Network packet size is 4096 and Remote Login Timeout is 120.
Please help regarding this asap as we want to go live. Now I will try other way round , I will install database at 2008 R2 and install window service at windows 2003.
Thanks
Amit.
|
|
|
|
|
Check the system's event log?
|
|
|
|
|
Is the SQL service running as a Network service?
If you go to Configuration Manager, in the SQL service Properties, it has to have the "log on as": Built in Account -> Network service.
Hope this helps.
http://gyazo.com/fc3c3d3cb790b6e71bad0f733fb6b264.png?1336464548
|
|
|
|
|
necesito un ajemplo para capturar la cantidad de paginas que se envian a imprimir y usarlo en c#...si alguien me pudiera ayudar se los agradeceria mucho...
|
|
|
|
|
This is an english-language site.
Please put your question in a translator and present its result to us.
No memory stick has been harmed during establishment of this signature.
|
|
|
|
|
Esto es principalmente un foro inglés. * Si usted publica en inglés, es posible que obtenga un sector más amplio de la comunidad para responder a su pregunta.
(This is mainly an English forum. If you post in English, you are likely to get a larger section of the community to answer your question).
|
|
|
|
|
samuelalvarito wrote: necesito un ajemplo para capturar la cantidad de paginas que se envian a imprimir y usarlo en c#...si alguien me pudiera ayudar se los agradeceria mucho...
Translation...
an example will need to capture the number of pages that are sent to print and use it in c # ... if someone could help me would appreciate it very much
I would be almost certain that google would be able to find examples of printing. And I suspect the same is true about your other questions. Translated that answer is...
Sería casi seguro que Google sería capaz de encontrar ejemplos de impresión. Y sospecho que lo mismo es cierto acerca de sus otras preguntas.
|
|
|
|
|
como interceptar la cantidad de paginas del documentos que se envian a imprimir para adaptarlo a c#
|
|
|
|
|
como usar el evento drag&drop para cargar documentos office en un formulario de c# y luego imprimirlos
|
|
|
|
|
If you post in English, you are likely to get a larger section of the community to answer your question.
|
|
|
|
|
Your form (or better: an element, e.g. a listview on it) has to subscribe for two events: DragEnter and DragDrop.
In DragEnter do something like:
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect = DragDropEffects.Copy;
else
e.Effect = DragDropEffects.None;
Now you'll get a "Plus" cursor when you drag the files into the element.
In DragDrop do something like:
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop, true);
foreach (string f in files)
{
}
}
Note that you get the filenames.
|
|
|
|
|
How do I know whether or not to call ReleaseComObject()?
For example in the following code I call ReleaseComObject() on the Worksheet, it works fine, but I dont rearly know if this is correct or not. How would I know? Is there a rule that I need to follow?
try
{
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
string strWorkBook = @"C:\zz\Book1.xlsx";
Workbook workBook = excelApp.Workbooks.Open(strWorkBook,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
int nSheets = workBook.Sheets.Count;
Worksheet sheet = (Worksheet)workBook.Sheets[1];
Marshal.ReleaseComObject(sheet);
workBook.Close(false, strWorkBook, null);
Marshal.ReleaseComObject(workBook);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
“If I had asked people what they wanted, they would have said faster horses.”
― Henry Ford
|
|
|
|
|
As a rule, its advisable to release com objects from managed code.
|
|
|
|
|
|
Hi...
I am using the following code to discover remote devices..using the UUID specified by the OBEX Specification..
But the devices are not being discovered..
Am i missing any other thread?
Thanks in advance...
private bool OBEXOpenStream(string BTMAC)
{
Guid spguid = new Guid("{(uuid128=F9EC7BC4-953C-11D2-984E-525400DC9E09)}");
btaddress = OpenNETCF.Net.BluetoothAddress.Parse(BTMAC);
client = new OpenNETCF.Net.Sockets.BluetoothClient();
endpoint = new OpenNETCF.Net.BluetoothEndPoint(btaddress, spguid);
try
{
client.Connect(endpoint);
}
catch (System.Exception e)
{
return false;
}
stream = client.GetStream();
return true;
}
modified 26-Apr-12 1:27am.
|
|
|
|