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 16 15853
Gerrit <gs*************@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.)
and than I have this:
<snip>
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 - <sk***@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
"Gerrit" <gs*************@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 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 - <sk***@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
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP***********************@msnews.microsoft.co m... Gerrit <gs*************@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.
"James Park" <so*****@hotmail.com> wrote in message
news:%2******************@TK2MSFTNGP09.phx.gbl... "Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message news:MP***********************@msnews.microsoft.co m... Gerrit <gs*************@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
"Bill Butler" <qw****@asdf.com> wrote in message
news:MmWEf.674$Zy3.238@trndny08... "James Park" <so*****@hotmail.com> wrote in message news:%2******************@TK2MSFTNGP09.phx.gbl... "Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message news:MP***********************@msnews.microsoft.co m... Gerrit <gs*************@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
So, why is it a bad idea in your case???
I'm not the OP, but that's okay. :)
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.
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.
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.
James Park <so*****@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 - <sk***@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
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om... James Park <so*****@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.
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.
James Park <so*****@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? (sk***@pobox.com) 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.
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.
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 - <sk***@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
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 :-)
"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 - <sk***@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
"James Park" <so*****@hotmail.com> wrote in message news:%2****************@tk2msftngp13.phx.gbl... "Bill Butler" <qw****@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
<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" <ki********@hotmail.comREMOVETRAIL> schreef in bericht
news:Oi**************@TK2MSFTNGP15.phx.gbl... 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 // ================================================== ===============
.........
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
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om... James Park <so*****@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? (sk***@pobox.com)
Sent. > 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. 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. 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?
"Bill Butler" <qw****@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
"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
James Park <so*****@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. 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.)
Btw, the total size under x64 would be 32 and not 28.
Oops, yes. 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 - <sk***@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 This discussion thread is closed Replies have been disabled for this discussion. Similar topics
7 posts
views
Thread by ritchie |
last post: by
|
3 posts
views
Thread by b83503104 |
last post: by
|
36 posts
views
Thread by Eric Laberge |
last post: by
|
11 posts
views
Thread by Cliff Martin |
last post: by
| |
4 posts
views
Thread by Santosh Nayak |
last post: by
|
2 posts
views
Thread by Santosh Nayak |
last post: by
|
5 posts
views
Thread by tienlx |
last post: by
|
36 posts
views
Thread by pereges |
last post: by
| | | | | | | | | | |