all groups > c# > february 2006 >
c# :
Array.Sort a struct
[quoted text, click to view] "Gerrit" <gsnel_geentroep@hotmail.com> wrote in message news:S0REf.4732$zc1.1422@amstwist00... > Hello, > > Is it possible to sort an array with a struct in it? > > example: > > I have a struct: > public struct mp3file > { > public int tracknr; > public int length; > public string filename; > public string artist; > public string title; > } > > and than I have this: > > mp3file[] mp3 = new mp3file[files.Length]; > int t = 0; > > foreach (FileInfo fi in files) > { > MP3File mp3File = ShellID3TagReader.ReadID3Tags(fi.FullName); > mp3[t].length = mp3File.Length; > mp3[t].artist = mp3File.ArtistName; > mp3[t].title = mp3File.SongTitle; > mp3[t].tracknr = mp3File.TrackNumber; > mp3[t].filename = mp3File.FileName; > t++; > } > > this is working, but now I want to sort the array by tracknr, so I can > make a playlist, sorted by tracknr. > with something like: > > Array.Sort(mp3.tracknr) > > but that doesn't work > > How can I do this? > > Thanks for your help! > -- > > www.gsnel.nl You'd have to create an IComparer class. The following *should* be what you need :) public struct mp3file { public int tracknr; public int length; public string filename; public string artist; public string title; } public class Class1 { public Class1() { } public void Mp3Files() { mp3file[] files = new mp3file[2]; files[0].tracknr = 2; files[0].length = 5000; files[0].filename = "blah2"; files[0].title = "Title 2"; files[1].tracknr = 1; files[1].length = 5000; files[1].filename = "blah1"; files[1].title = "Title 1"; Array.Sort(files, new Mp3FileComparer()); foreach (mp3file file in files) { Console.WriteLine(file.tracknr); } } } public class Mp3FileComparer : System.Collections.IComparer { public Mp3FileComparer() { } public int Compare(object Object1, object Object2) { if (!(Object1 is mp3file)) { throw new ArgumentException( "Object1 must be of type mp3file.", "Object1" ); } else if (!(Object2 is mp3file)) { throw new ArgumentException( "Object2 must be of type mp3file.", "Object2" ); } int n1 = ((mp3file) Object1).tracknr; int n2 = ((mp3file) Object2).tracknr; if (n1 > n2) { return 1; } else if (n1 == n2) { return 0; } else { return -1; } } } HTH :) Mythran
[quoted text, click to view] > You still want to sort the array, so you need to call Array.Sort with > mp3 as one parameter - but there's an overload which takes an IComparer > (or one which takes an IComparer<T> if you're using .NET 2.0) which is > used for the sorting. You need to implement IComparer in some class or > other to descibe the ordering you want. > > -- > Jon Skeet - <skeet@pobox.com> > http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet > If replying to the group, please do not mail me too And to extend on what Jon was stating...the following is v1.1 code and uses the IComparable interface instead of the IComparer interface. The MP3File class implements this interface and containts the implementation of CompareTo, which is all Array.Sort method needs to sort the class (notice, it is no longer just a struct, but a full class w/o comments). public class MP3File : IComparable { #region Private Members // ================================================================= // Private Members // ================================================================= private int mTrackNumber; private int mLength; private string mFileName; private string mArtist; private string mTitle; #endregion #region Constructors / Destructors // ================================================================= // Constructors / Destructors // ================================================================= public MP3File() { } #endregion #region Public Properties // ================================================================= // Public Properties // ================================================================= public int TrackNumber { get { return mTrackNumber; } set { mTrackNumber = value; } } public int Length { get { return mLength; } set { mLength = value; } } public string FileName { get { return mFileName; } set { mFileName = value; } } public string Artist { get { return mArtist; } set { mArtist = value; } } public string Title { get { return mTitle; } set { mTitle = value; } } #endregion #region Public Methods // ================================================================= // Public Methods // ================================================================= public int CompareTo(object obj) { if (!(obj is MP3File)) { throw new ArgumentException( "Argument 'obj' is not of type MP3File.", "obj" ); } int num = ((MP3File) obj).TrackNumber; if (this.TrackNumber < num) { return -1; } else if (this.TrackNumber == num) { return 0; } else { return 1; } } public override string ToString() { return string.Format( "{0} : {1} : {2}", this.TrackNumber, this.Artist, this.Title ); } #endregion } /// The following class should be created and the Mp3Files method called to /// test the functionality of the MP3File and IComparable. public class Class1 { public Class1() { } public void Mp3Files() { MP3File[] files = new MP3File[3]; files[0] = new MP3File(); files[0].TrackNumber = 3; files[0].Length = 5000; files[0].Artist = "Me"; files[0].FileName = "MyFileName3"; files[0].Title = "Title 3"; files[1] = new MP3File(); files[1].TrackNumber = 1; files[1].Length = 23422; files[1].Artist = "My"; files[1].FileName = "MyFileName1"; files[1].Title = "Title 1"; files[2] = new MP3File(); files[2].TrackNumber = 2; files[2].Length = 23421; files[2].Artist = "Mine"; files[2].FileName = "MyFileName2"; files[2].Title = "Title 2"; Array.Sort(files); foreach (MP3File file in files) { Console.WriteLine(file); } } } :) HTH some more. Mythran
[quoted text, click to view] "Jon Skeet [C# MVP]" <skeet@pobox.com> wrote in message news:MPG.1e4df14b970b86898cdc0@msnews.microsoft.com... > Gerrit <gsnel_geentroep@hotmail.com> wrote: >> Is it possible to sort an array with a struct in it? >> >> example: >> >> I have a struct: >> public struct mp3file >> { >> public int tracknr; >> public int length; >> public string filename; >> public string artist; >> public string title; >> } > > Why is this a struct? That seems like a bad idea to me. (I'd also > suggest that you don't have public fields, by the way.)
Why is it being a struct a bad idea? I just read the "Structs Tutorial" on MSDN and it said "Whenever you have a need for a type that will be used often and is mostly just a piece of data, structs might be a good option." It looks like all data to me, so if you could clear up what's bad about it, that'd be great.
[quoted text, click to view] "Bill Butler" <qwerty@asdf.com> wrote in message news:MmWEf.674$Zy3.238@trndny08... > > "James Park" <someone@hotmail.com> wrote in message > news:%236MU%23uSKGHA.3492@TK2MSFTNGP09.phx.gbl... >> "Jon Skeet [C# MVP]" <skeet@pobox.com> wrote in message >> news:MPG.1e4df14b970b86898cdc0@msnews.microsoft.com... >>> Gerrit <gsnel_geentroep@hotmail.com> wrote: >>>> Is it possible to sort an array with a struct in it? >>>> >>>> example: >>>> >>>> I have a struct: >>>> public struct mp3file >>>> { >>>> public int tracknr; >>>> public int length; >>>> public string filename; >>>> public string artist; >>>> public string title; >>>> } >>> >>> Why is this a struct? That seems like a bad idea to me. (I'd also >>> suggest that you don't have public fields, by the way.) >> >> Why is it being a struct a bad idea? I just read the "Structs Tutorial" >> on MSDN and it said "Whenever you have a need for a type that will be >> used often and is mostly just a piece of data, structs might be a good >> option." It looks like all data to me, so if you could clear up what's >> bad about it, that'd be great. > > Hi James,
Hi Bill [quoted text, click to view] > So, why is it a bad idea in your case???
I'm not the OP, but that's okay. :) [quoted text, click to view] > Passing your struct to a function is more expensive than passing the same > data as a class, since the struct has to be totally copied whereas only > the reference to the class needs to be copied. Granted, your struct is not > huge, but it will still be slower (like that Sort you were asking about).
I ran some Stopwatch tests on Mythran's code. As written (sample size 200,000): structs: 2998 milliseconds classes: 368 milliseconds <-- winner Modified to use generics (sample size 2,000,000): structs: 1508 milliseconds <-- winner classes: 2213 milliseconds I'm not savvy enough to speculate why the performance balance shifts, but it indeed does. [quoted text, click to view] > There are other subtle gotchas as well. > Take the following code. > ---------------------------------- > Thing myThing = new Thing(/*blah*/); > Foo(myThing ); > > public void Foo(Thing thing) > { > thing.X = 3; > } > --------------------------------- > Will myThing be modified?? > YES:If it is a class > NO : If it is a struct > > Most C# programmers will expect the code to work (Assume it is a class) > Without looking at the declaration of your struct it is hard to tell that > it is not a class. > Subtle bugs are the result.
I wouldn't think this would be such a problem, but then again I don't have a good feel for how frequently that misunderstanding would occur or how much time would be wasted on it. [quoted text, click to view] > If you are using struct over class as an optimization....DON'T. > Test it for yourself if you don't believe us. > Classes are almost always the right way to go > > There ARE good uses of struct in C#, but in general, you should use > classes. > In C# structs are kind of like gotos > Both can be useful in certain optimization situations, but I would REALLY > think twice before using one without a very good reason.
Personally, I only use structs for P/Invoke stuff, but I'd like to know other situations where they should be used. It just seemed to me that this could be a legitimate situation.
[quoted text, click to view] Gerrit <gsnel_geentroep@hotmail.com> wrote: > Is it possible to sort an array with a struct in it? > > example: > > I have a struct: > public struct mp3file > { > public int tracknr; > public int length; > public string filename; > public string artist; > public string title; > }
Why is this a struct? That seems like a bad idea to me. (I'd also suggest that you don't have public fields, by the way.) [quoted text, click to view] > and than I have this:
<snip> [quoted text, click to view] > this is working, but now I want to sort the array by tracknr, so I can make > a playlist, sorted by tracknr. > with something like: > > Array.Sort(mp3.tracknr) > > but that doesn't work > > How can I do this?
You still want to sort the array, so you need to call Array.Sort with mp3 as one parameter - but there's an overload which takes an IComparer (or one which takes an IComparer<T> if you're using .NET 2.0) which is used for the sorting. You need to implement IComparer in some class or other to descibe the ordering you want. -- Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
Hello, Is it possible to sort an array with a struct in it? example: I have a struct: public struct mp3file { public int tracknr; public int length; public string filename; public string artist; public string title; } and than I have this: mp3file[] mp3 = new mp3file[files.Length]; int t = 0; foreach (FileInfo fi in files) { MP3File mp3File = ShellID3TagReader.ReadID3Tags(fi.FullName); mp3[t].length = mp3File.Length; mp3[t].artist = mp3File.ArtistName; mp3[t].title = mp3File.SongTitle; mp3[t].tracknr = mp3File.TrackNumber; mp3[t].filename = mp3File.FileName; t++; } this is working, but now I want to sort the array by tracknr, so I can make a playlist, sorted by tracknr. with something like: Array.Sort(mp3.tracknr) but that doesn't work How can I do this? Thanks for your help! -- www.gsnel.nl
[quoted text, click to view] "Jon Skeet [C# MVP]" <skeet@pobox.com> wrote in message news:MPG.1e4e5fffdd55eeb298cdc2@msnews.microsoft.com... > James Park <someone@hotmail.com> wrote: >> > Why is this a struct? That seems like a bad idea to me. (I'd also >> > suggest that you don't have public fields, by the way.) >> >> Why is it being a struct a bad idea? I just read the "Structs Tutorial" >> on >> MSDN and it said "Whenever you have a need for a type that will be used >> often and is mostly just a piece of data, structs might be a good >> option." >> It looks like all data to me, so if you could clear up what's bad about >> it, >> that'd be great. > > That's just a bad article, unfortunately. It's incorrect in terms of > heap vs stack, too - see http://www.pobox.com/~skeet/csharp/memory.html Good to know. By the way, my browser is cutting the code examples in your article off on the right side, but it may be because I'm using the IE7 beta. [quoted text, click to view] > Whether you want to use a struct or a class has nothing to with whether > it's "just a piece of data". See my reply on the thread "Structure v/s > classes" for more information.
Here's my take. 1) It looks like the type is atomic (assuming my interpretation of the word's definition is right). 2) It doesn't look like a lot of data needs to be stored. 3) Depending on how the type is used, it may or may not need to be mutable. Hmm, it still looks like a struct could be used. Maybe I could use some more clarification.
[quoted text, click to view] James Park <someone@hotmail.com> wrote: > > That's just a bad article, unfortunately. It's incorrect in terms of > > heap vs stack, too - see http://www.pobox.com/~skeet/csharp/memory.html > > Good to know. By the way, my browser is cutting the code examples in your > article off on the right side, but it may be because I'm using the IE7 beta. Wow, that's odd - the examples are pretty narrow. Could you mail me a screenshot? (skeet@pobox.com) [quoted text, click to view] > > Whether you want to use a struct or a class has nothing to with whether > > it's "just a piece of data". See my reply on the thread "Structure v/s > > classes" for more information. > > Here's my take. > 1) It looks like the type is atomic (assuming my interpretation of the > word's definition is right).
It's not really - it makes sense to modify each of the fields individually. It's a collection of data about something. [quoted text, click to view] > 2) It doesn't look like a lot of data needs to be stored.
There are 2 ints and 3 references, which means 20 bytes on x86 or 28 bytes on x64. Now performance isn't really an issue most of the time, but it means that any time an mp3file is passed to a method, it's got to copy all 20 or 28 bytes into the parameter (and likewise if one is returned). That's like having 5 or 7 reference type parameters. When it comes to sorting the array, that's going to be slower than sorting it if mp3file were a reference type - then only the references would need to be shuffled around, instead of of all the data. [quoted text, click to view] > 3) Depending on how the type is used, it may or may not need to be mutable. > > Hmm, it still looks like a struct could be used. Maybe I could use some more > clarification.
Well a struct *could* be used - but it feels like the wrong decision to me. I don't see any reason why value type semantics would be desired in this case. -- Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
[quoted text, click to view] James Park <someone@hotmail.com> wrote: > > Why is this a struct? That seems like a bad idea to me. (I'd also > > suggest that you don't have public fields, by the way.) > > Why is it being a struct a bad idea? I just read the "Structs Tutorial" on > MSDN and it said "Whenever you have a need for a type that will be used > often and is mostly just a piece of data, structs might be a good option." > It looks like all data to me, so if you could clear up what's bad about it, > that'd be great.
That's just a bad article, unfortunately. It's incorrect in terms of heap vs stack, too - see http://www.pobox.com/~skeet/csharp/memory.html Whether you want to use a struct or a class has nothing to with whether it's "just a piece of data". See my reply on the thread "Structure v/s classes" for more information. -- Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
[quoted text, click to view] "James Park" <someone@hotmail.com> wrote in message news:%236MU%23uSKGHA.3492@TK2MSFTNGP09.phx.gbl... > "Jon Skeet [C# MVP]" <skeet@pobox.com> wrote in message > news:MPG.1e4df14b970b86898cdc0@msnews.microsoft.com... >> Gerrit <gsnel_geentroep@hotmail.com> wrote: >>> Is it possible to sort an array with a struct in it? >>> >>> example: >>> >>> I have a struct: >>> public struct mp3file >>> { >>> public int tracknr; >>> public int length; >>> public string filename; >>> public string artist; >>> public string title; >>> } >> >> Why is this a struct? That seems like a bad idea to me. (I'd also >> suggest that you don't have public fields, by the way.) > > Why is it being a struct a bad idea? I just read the "Structs Tutorial" on MSDN and it said > "Whenever you have a need for a type that will be used often and is mostly just a piece of data, > structs might be a good option." It looks like all data to me, so if you could clear up what's bad > about it, that'd be great.
Hi James, // First C++ If you pass a struct to a function it will be copied (value semantics). If you want reference semantics, you pass in a pointer or a reference. Now C# structs in C# act ALOT like C++ structs. If you pass it into a function you will get a copy of the struct and not the original struct. This is where C# Classes come in. You NEVER deal directly with an object, You ALWAYS deal with a reference to the object. Unlike C++ reference, which cannot be reassigned, C# references are more like auto dereferenced pointers. So, why is it a bad idea in your case??? Passing your struct to a function is more expensive than passing the same data as a class, since the struct has to be totally copied whereas only the reference to the class needs to be copied. Granted, your struct is not huge, but it will still be slower (like that Sort you were asking about). There are other subtle gotchas as well. Take the following code. ---------------------------------- Thing myThing = new Thing(/*blah*/); Foo(myThing ); public void Foo(Thing thing) { thing.X = 3; } --------------------------------- Will myThing be modified?? YES:If it is a class NO : If it is a struct Most C# programmers will expect the code to work (Assume it is a class) Without looking at the declaration of your struct it is hard to tell that it is not a class. Subtle bugs are the result. If you are using struct over class as an optimization....DON'T. Test it for yourself if you don't believe us. Classes are almost always the right way to go There ARE good uses of struct in C#, but in general, you should use classes. In C# structs are kind of like gotos Both can be useful in certain optimization situations, but I would REALLY think twice before using one without a very good reason. Bill
I would also add a constrctor while you are at it that takes all of the default parameters, so: files[2] = new MP3File(); files[2].TrackNumber = 2; files[2].Length = 23421; files[2].Artist = "Mine"; files[2].FileName = "MyFileName2"; files[2].Title = "Title 2"; is replaced by: files[2] = new MP3File(2, 23421, "Mine", "MyFileName2", "Title 2"); which nicely cuts down on the bulk of the code, IMO :-) [quoted text, click to view] "Mythran" wrote: > > > You still want to sort the array, so you need to call Array.Sort with > > mp3 as one parameter - but there's an overload which takes an IComparer > > (or one which takes an IComparer<T> if you're using .NET 2.0) which is > > used for the sorting. You need to implement IComparer in some class or > > other to descibe the ordering you want. > > > > -- > > Jon Skeet - <skeet@pobox.com> > > http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet > > If replying to the group, please do not mail me too > > And to extend on what Jon was stating...the following is v1.1 code and uses > the IComparable interface instead of the IComparer interface. The MP3File > class implements this interface and containts the implementation of > CompareTo, which is all Array.Sort method needs to sort the class (notice, > it is no longer just a struct, but a full class w/o comments). > > public class MP3File : IComparable > { > > #region Private Members > // ================================================================= > // Private Members > // ================================================================= > > private int mTrackNumber; > private int mLength; > private string mFileName; > private string mArtist; > private string mTitle; > #endregion > > #region Constructors / Destructors > // ================================================================= > // Constructors / Destructors > // ================================================================= > > public MP3File() { } > #endregion > > #region Public Properties > // ================================================================= > // Public Properties > // ================================================================= > > public int TrackNumber > { > get { return mTrackNumber; } > set { mTrackNumber = value; } > } > > public int Length > { > get { return mLength; } > set { mLength = value; } > } > > public string FileName > { > get { return mFileName; } > set { mFileName = value; } > } > > public string Artist > { > get { return mArtist; } > set { mArtist = value; } > } > > public string Title > { > get { return mTitle; } > set { mTitle = value; } > } > #endregion > > #region Public Methods > // ================================================================= > // Public Methods > // ================================================================= > > public int CompareTo(object obj) > { > if (!(obj is MP3File)) { > throw new ArgumentException( > "Argument 'obj' is not of type MP3File.", > "obj" > ); > } > > int num = ((MP3File) obj).TrackNumber; > if (this.TrackNumber < num) { > return -1; > } else if (this.TrackNumber == num) { > return 0; > } else { > return 1; > } > } > > public override string ToString() > { > return string.Format( > "{0} : {1} : {2}", > this.TrackNumber, > this.Artist, > this.Title > ); > } > #endregion > > } > > /// The following class should be created and the Mp3Files method called to > /// test the functionality of the MP3File and IComparable. > public class Class1 > { > > public Class1() { } > > public void Mp3Files() > { > MP3File[] files = new MP3File[3]; > > files[0] = new MP3File(); > files[0].TrackNumber = 3; > files[0].Length = 5000; > files[0].Artist = "Me"; > files[0].FileName = "MyFileName3"; > files[0].Title = "Title 3"; > > files[1] = new MP3File(); > files[1].TrackNumber = 1; > files[1].Length = 23422; > files[1].Artist = "My"; > files[1].FileName = "MyFileName1"; > files[1].Title = "Title 1"; > > files[2] = new MP3File(); > files[2].TrackNumber = 2; > files[2].Length = 23421; > files[2].Artist = "Mine"; > files[2].FileName = "MyFileName2"; > files[2].Title = "Title 2"; > > Array.Sort(files); > > foreach (MP3File file in files) { > Console.WriteLine(file); > } > } > } > > :) > > HTH some more. > > Mythran >
[quoted text, click to view] "Jon Skeet [C# MVP]" <skeet@pobox.com> wrote in message news:MPG.1e4e7662124f96a498cdc3@msnews.microsoft.com... > James Park <someone@hotmail.com> wrote: >> > That's just a bad article, unfortunately. It's incorrect in terms of >> > heap vs stack, too - see http://www.pobox.com/~skeet/csharp/memory.html >> >> Good to know. By the way, my browser is cutting the code examples in your >> article off on the right side, but it may be because I'm using the IE7 >> beta. > > Wow, that's odd - the examples are pretty narrow. Could you mail me a > screenshot? (skeet@pobox.com) Sent. [quoted text, click to view] >> > Whether you want to use a struct or a class has nothing to with whether >> > it's "just a piece of data". See my reply on the thread "Structure v/s >> > classes" for more information. >> >> Here's my take. >> 1) It looks like the type is atomic (assuming my interpretation of the >> word's definition is right). > > It's not really - it makes sense to modify each of the fields > individually. It's a collection of data about something.
I think it depends on the type of program. If it's like an editor and can modify the mp3 file itself, then sure, the fields are pretty much fair game individually. If it's like a player and isn't supposed to modify the file, then it wouldn't make sense to mess with individual fields. [quoted text, click to view] >> 2) It doesn't look like a lot of data needs to be stored. > > There are 2 ints and 3 references, which means 20 bytes on x86 or 28 > bytes on x64. Now performance isn't really an issue most of the time, > but it means that any time an mp3file is passed to a method, it's got > to copy all 20 or 28 bytes into the parameter (and likewise if one is > returned). That's like having 5 or 7 reference type parameters. > > When it comes to sorting the array, that's going to be slower than > sorting it if mp3file were a reference type - then only the references > would need to be shuffled around, instead of of all the data.
I found sorting the array was actually faster using structs. In fact, when I originally tested in my other post, I didn't assign any of the string fields. Doing that, the structs performed just as quickly, but the classes were bogged down even more (classes took twice as long as structs afterward). The performance may shift drastically using x64, but I don't have the OS installed to test it. Btw, the total size under x64 would be 32 and not 28. [quoted text, click to view] >> 3) Depending on how the type is used, it may or may not need to be >> mutable. >> >> Hmm, it still looks like a struct could be used. Maybe I could use some >> more >> clarification. > > Well a struct *could* be used - but it feels like the wrong decision to > me. I don't see any reason why value type semantics would be desired in > this case.
I found some more advice in the MSDN article "Value Type Usage Guidelines" It is recommended that you use a struct for types that meet any of the following criteria: Act like primitive types. Have an instance size under 16 bytes. Are immutable. Value semantics are desirable. I think the answers here are no, no, maybe, and maybe (if sorting performance is an issue and I did the test correctly). Would it be fair to say this article is more accurate as to what should be a struct?
[quoted text, click to view] "Bill Butler" <qwerty@asdf.com> wrote in message news:oo5Ff.693$Zy3.477@trndny08... > Many people come the C# with a C++ mindset and choose structs over classes > for the wrong reasons. > They will ,by default, choose a struct over a class for a Plain Old > Data(POD) type. > They do this because they think of a struct as a lightweight class ( ie > faster). > They figure that they don't need that object baggage (methods and stuff) > In short, they do it to improve performance. > More often than not they actually get worse performance due to boxing and > full copying on method calls. > > Objects access in c# is quite fast and most Properties will get inlined by > the JITer, so POD types should ,by default, be classes. > > So, when should you consider converting your class to a struct? > Suppose you have a small object (not expensive to copy) and you create > alot of them in tight looping situations (a Point comes to mind.) . The > potential performance improvement comes from faster creation of the struct > on the stack. This is offset against longer method call times (unless the > struct is tiny),and Boxing (although generics can help). So if you have > tiny , immutable objects that you create frequently and it is effecting > performance, you MIGHT get a performance boost by changing it to a class. > The important thing to note is that it is the cost of creation that you > are saving. So structs might help in short lifetime conditions. The choice > should NOT be made lightly. > > In C# the object should always be the DEFAULT unit of data storage. > In most situations it will outperform structs. > > In the specific case of Gerrit's Playlist. > The data MIGHT be immutable (at least it is in his quick sample) > The data is NOT created frequently (he creates 1 for each file in a > folder) > His struct is small but not Tiny (more expensive method calls). > > So, He could use a stuct to represent his data and most likely only suffer > a small performance hit. > Of course that depends on the actual logic. > > The real point is that he probably chose the struct over a class in order > to make it MORE performant. > It is doubtful that the end result will bear this out. > This is why we tend to steer developers away from structs.
Thanks for the good explanation Bill.
Hi Gerrit, to the sort method you need to pass your array but also some logic that know how to compare based on the desired property of your struct. There are many overloads in the Sort method but one way to do it is using the Comparison<T> delegate like below: static void Main(string[] args) { mp3file m1 = new mp3file(); m1.tracknr = 20; mp3file m2 = new mp3file(); m2.tracknr = 10; mp3file[] arr = new mp3file[2]; arr[0] = m1; arr[1] = m2; Array.Sort(arr, delegate(mp3file file1, mp3file file2) { return file1.tracknr.CompareTo(file2.tracknr); }); } If you dont want to use the Comparison<T> then you can use something else like creating an object that implements the IComparer interface (a quick look in google should show you how to use that). Hope that helps Mark Dawson www.markdawson.org [quoted text, click to view] "Gerrit" wrote: > Hello, > > Is it possible to sort an array with a struct in it? > > example: > > I have a struct: > public struct mp3file > { > public int tracknr; > public int length; > public string filename; > public string artist; > public string title; > } > > and than I have this: > > mp3file[] mp3 = new mp3file[files.Length]; > int t = 0; > > foreach (FileInfo fi in files) > { > MP3File mp3File = ShellID3TagReader.ReadID3Tags(fi.FullName); > mp3[t].length = mp3File.Length; > mp3[t].artist = mp3File.ArtistName; > mp3[t].title = mp3File.SongTitle; > mp3[t].tracknr = mp3File.TrackNumber; > mp3[t].filename = mp3File.FileName; > t++; > } > > this is working, but now I want to sort the array by tracknr, so I can make > a playlist, sorted by tracknr. > with something like: > > Array.Sort(mp3.tracknr) > > but that doesn't work > > How can I do this? > > Thanks for your help! > -- > > www.gsnel.nl > >
[quoted text, click to view] "James Park" <someone@hotmail.com> wrote in message news:%23oqOZBVKGHA.3728@tk2msftngp13.phx.gbl... > "Bill Butler" <qwerty@asdf.com> wrote in message news:MmWEf.674$Zy3.238@trndny08... >> <snip> >> So, why is it a bad idea in your case??? > > I'm not the OP, but that's okay. :)
Ooops, sorry about that [quoted text, click to view] > <snip> > > Personally, I only use structs for P/Invoke stuff, but I'd like to know other situations where > they should be used. It just seemed to me that this could be a legitimate situation.
Many people come the C# with a C++ mindset and choose structs over classes for the wrong reasons. They will ,by default, choose a struct over a class for a Plain Old Data(POD) type. They do this because they think of a struct as a lightweight class ( ie faster). They figure that they don't need that object baggage (methods and stuff) In short, they do it to improve performance. More often than not they actually get worse performance due to boxing and full copying on method calls. Objects access in c# is quite fast and most Properties will get inlined by the JITer, so POD types should ,by default, be classes. So, when should you consider converting your class to a struct? Suppose you have a small object (not expensive to copy) and you create alot of them in tight looping situations (a Point comes to mind.) . The potential performance improvement comes from faster creation of the struct on the stack. This is offset against longer method call times (unless the struct is tiny),and Boxing (although generics can help). So if you have tiny , immutable objects that you create frequently and it is effecting performance, you MIGHT get a performance boost by changing it to a class. The important thing to note is that it is the cost of creation that you are saving. So structs might help in short lifetime conditions. The choice should NOT be made lightly. In C# the object should always be the DEFAULT unit of data storage. In most situations it will outperform structs. In the specific case of Gerrit's Playlist. The data MIGHT be immutable (at least it is in his quick sample) The data is NOT created frequently (he creates 1 for each file in a folder) His struct is small but not Tiny (more expensive method calls). So, He could use a stuct to represent his data and most likely only suffer a small performance hit. Of course that depends on the actual logic. The real point is that he probably chose the struct over a class in order to make it MORE performant. It is doubtful that the end result will bear this out. This is why we tend to steer developers away from structs. Bill
"Mythran" <kip_potter@hotmail.comREMOVETRAIL> schreef in bericht news:OidbtsRKGHA.2248@TK2MSFTNGP15.phx.gbl... [quoted text, click to view] > And to extend on what Jon was stating...the following is v1.1 code and > uses the IComparable interface instead of the IComparer interface. The > MP3File class implements this interface and containts the implementation > of CompareTo, which is all Array.Sort method needs to sort the class > (notice, it is no longer just a struct, but a full class w/o comments). > > public class MP3File : IComparable > { > > #region Private Members > // > ================================================================= > // Private Members > // > =================================================================
......... [quoted text, click to view] > files[2].Title = "Title 2"; > > Array.Sort(files); > > foreach (MP3File file in files) { > Console.WriteLine(file); > } > }
I'm new with C# and my English is not very good, so I don 't understand exactly the discussion about the difference between the use of a struct or a class in this case, but with this code, my program is working how I want it must working. So thank you very much. Gerrit -- www.gsnel.nl
[quoted text, click to view] James Park <someone@hotmail.com> wrote: > >> Here's my take. > >> 1) It looks like the type is atomic (assuming my interpretation of the > >> word's definition is right). > > > > It's not really - it makes sense to modify each of the fields > > individually. It's a collection of data about something. > > I think it depends on the type of program. If it's like an editor and can > modify the mp3 file itself, then sure, the fields are pretty much fair game > individually. If it's like a player and isn't supposed to modify the file, > then it wouldn't make sense to mess with individual fields.
But the point is that *logically* it makes sense for them to be mutable. They are, in some ways, independent values, even though the all refer to the same file. [quoted text, click to view] > > When it comes to sorting the array, that's going to be slower than > > sorting it if mp3file were a reference type - then only the references > > would need to be shuffled around, instead of of all the data. > > I found sorting the array was actually faster using structs. In fact, when I > originally tested in my other post, I didn't assign any of the string > fields. Doing that, the structs performed just as quickly, but the classes > were bogged down even more (classes took twice as long as structs > afterward). The performance may shift drastically using x64, but I don't > have the OS installed to test it.
I suspect that will depend on how many entries you've got - more memory in total will be used for classes, but shifting each entry around will be easier. If everything fits in the cache for structs but not for classes, that could explain the difference - otherwise I really would expect it to be faster for classes. (It partly depends on whether you're sorting using IComparer, IComparer<T> or IComparable - with plain IComparer you have to box on every comparison too when using structs.) [quoted text, click to view] > Btw, the total size under x64 would be 32 and not 28.
Oops, yes. [quoted text, click to view] > > Well a struct *could* be used - but it feels like the wrong decision to > > me. I don't see any reason why value type semantics would be desired in > > this case. > > I found some more advice in the MSDN article "Value Type Usage Guidelines" > > It is recommended that you use a struct for types that meet any of the > following criteria: > Act like primitive types. > Have an instance size under 16 bytes. > Are immutable. > Value semantics are desirable. > > I think the answers here are no, no, maybe, and maybe (if sorting > performance is an issue and I did the test correctly). Would it be fair to > say this article is more accurate as to what should be a struct?
Yes - that's much, much better. -- Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
Don't see what you're looking for? Try a search.
|
|
|