Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
Uziel
Jun 28, 2004

Ask me about losing 200lbs, and becoming the Viking God of W&W.
Are there any recommended resources for getting started with WPF in .net4.0? I mostly work on web stuff but have a project that needs to be a desktop app.

Adbot
ADBOT LOVES YOU

epswing
Nov 4, 2003

Soiled Meat
WPF 4 Unleashed was a good read, full of examples and screenshots.

PDP-1
Oct 12, 2004

It's a beautiful day in the neighborhood.
Anyone have any suggestions for how to incorporate a nice C# script editor into a program? Right now I'm just using a regular textbox as an editor and then compiling that result and running it. This works, but the lack of editing/formatting/intellisense tools makes it feel clunky as heck and the user has to know what objects/methods are available by memory alone.

I've checked out several projects posted around the internet but none of them really look all that great. Ideally I'd like to pop open a scripting form, tell it what objects the script is allowed to access, and then have it feel as much like a mini version of Visual Studio as possible.

epswing
Nov 4, 2003

Soiled Meat
Take a look at how LINQPad does it: http://www.linqpad.net/HowLINQPadWorks.aspx

quote:

LINQPad uses a number of third-party components within the UI. The query editor uses Actipro's SyntaxEditor control (a very polished product); the "IntelliSense" features rely on a combination of libraries from Actipro Software and ICSharpCode (from the SharpDevelop project).

Factor Mystic
Mar 20, 2006

Baby's First Post-Apocalyptic Fiction
Is it possible to have a gradient run the length of an arc in WPF? I have seen this post which seems to indicate a goofy amount of code is required (so, par for WPF) but the example is a geometry path, not an arc, so I'm hoping to find some trick that will make it simple.

raminasi
Jan 25, 2005

a last drink with no ice
If I've got to marshal a goofy hierarchy of structures including dynamically-allocated native arrays, is it reasonable that I'm going to end up doing pointer arithmetic on some IntPtrs? I can't find anything useful in Marshal for "copy this as a variable-length array of this type."

Also, do I need to pin value types that live on the stack if I'm P/Invoking them into native code?

raminasi fucked around with this message at 00:10 on Dec 20, 2011

Sedro
Dec 31, 2008
P/Invoking with variable length arrays is kind of a pain in the rear end. Fixed length you can use MarshalAs.SizeConst but you already knew that.

If you're marshalling a variable length array of primitives, you can use various overloads of Marshal.Copy:
code:
var array = new double[] { ... };
var hGlobal = Marshal.AllocHGlobal(sizeof(double) * array.Length);

try
{
    Marshal.Copy(array, 0, hGlobal, array.Length);
    // stuff
}
finally
{
    Marshal.GlobalFree(hGlobal);
}
If you're marshalling variable length by-val arrays of complex structures, your best bet is to convert them to byte[]. The least painful way, although inefficient, is to marshal them out and back in as seen here. Then use the above code. You might end up doing IntPtr arithmetic.

You only need to pin reference types (especially callbacks) so the unmanaged pointer doesn't outlive the managed object.

Admiral Snackbar
Mar 13, 2006

OUR SNEEZE SHIELDS CANNOT REPEL A HUNGER OF THAT MAGNITUDE
I'm working on a small project in c# and have a quick question: I created a class that inherits Object and overrides .Equals(). The compiler is warning me because I am not overriding .GetHash() as well. Do I really need to do this if I'm never actually going to use that method myself?

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!
Just do it and return base.GetHashCode(). Note that you may have decreased performance when you use your object in various collections that use hashing, like a Dictionary.

No Pants
Dec 10, 2000

Admiral Snackbar posted:

I'm working on a small project in c# and have a quick question: I created a class that inherits Object and overrides .Equals(). The compiler is warning me because I am not overriding .GetHash() as well. Do I really need to do this if I'm never actually going to use that method myself?
It depends on what you're using that class for, but you probably don't need to override GetHashCode. You should just have it return a constant value in case something else uses that function.

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Admiral Snackbar posted:

I created a class that inherits Object

All classes inherit from object. :confused:

rolleyes
Nov 16, 2006

Sometimes you have to roll the hard... two?

Ithaqua posted:

All classes inherit from object. :confused:

I know you're trying to get exactly this response to prove the point, but presumably he means it inherits directly from object with no intermediary class(es).

wellwhoopdedooo
Nov 23, 2007

Pound Trooper!

Admiral Snackbar posted:

I'm working on a small project in c# and have a quick question: I created a class that inherits Object and overrides .Equals(). The compiler is warning me because I am not overriding .GetHash() as well. Do I really need to do this if I'm never actually going to use that method myself?

The other answers you got are fairly lovely, since they don't explain why you should or shouldn't override .GetHashCode().

You should override .GetHashCode() if two different instantiations of your class should be considered equal depending on their state. This is almost always the case when you're overriding .Equals(), otherwise you wouldn't bother overriding it, so the advice to not override it is probably wrong. You will not simply get decreased performance for calling base.GetHashCode()--you'll get different behavior.

See the following:
Without .GetHashCode() override
With .GetHashCode() override

If your value-typed object has more than one value that determines equality, you should combine the hashes. A fairly terrible way to do it is to simply:

return value1.GetHashCode() ^ value2.GetHashCode();

Ignore everything after this if it's for homework

Better, but still lovely is:

code:
public int GetHashCode ()
{
  // This is a prime number, I use it because it's easy to remember, but you
  // can replace it with any prime that's got roughly an even distribution of
  // 1/0 bits.
  var hash = unchecked((int)0xABadCab5);
  
  // 23 is also a prime number, you can replace it with any other relatively
  // small prime, but you want to shift stuff enough to make a difference so
  // don't use 3-7. I think 31 ends up making "better" hashes for some magical
  // reason.
  hash = unchecked(hash * 23 ^ LeastImportantMember.GetHashCode());
  hash = unchecked(hash * 23 ^ MostImportantMember.GetHashCode());
  
  return hash;
}
The most important values cause the biggest change in the hash, as the multiply causes some bits to be lost--think of it as a left-shift that doesn't just zero-fill. The above implementation is terrible, but very simple to remember and will ... probably ... be better than the plain XOR version. If you have more than 7 members that need to go into the hash (if using 23--multiply 1 * 23 7 times and remember max uint is ~4 billion), you'll need a different implementation (I think).

wellwhoopdedooo fucked around with this message at 01:34 on Dec 21, 2011

Zhentar
Sep 28, 2003

Brilliant Master Genius

wellwhoopdedooo posted:

The other answers you got are fairly lovely, since they don't explain why you should or shouldn't override .GetHashCode().

You still didn't explain why! Though you at least demonstrated it.

Even if your own code never calls .GetHashCode(), infrastructure (such as the Dictionary class) does call it, and depends upon hash code equality being equivalent to object equality.

No Pants
Dec 10, 2000

Zhentar posted:

You still didn't explain why! Though you at least demonstrated it.

Even if your own code never calls .GetHashCode(), infrastructure (such as the Dictionary class) does call it, and depends upon hash code equality being equivalent to object equality.
They aren't entirely equivalent. The only real rule is that two instances need to return the same hash code if they are equal.

Sedro
Dec 31, 2008

No Pants posted:

It depends on what you're using that class for, but you probably don't need to override GetHashCode. You should just have it return a constant value in case something else uses that function.
This advice is still valid. Returning a constant will result in a hash collision and fall back on Equals every time. See here. It's not much trouble to just implement it though.

Dietrich
Sep 11, 2001

No Pants posted:

It depends on what you're using that class for, but you probably don't need to override GetHashCode. You should just have it return a constant value in case something else uses that function.

:ughh:

Do not do this. Never, ever do this.

If your object has a logical key, return its hash.
pre:
return CustomerId.GetHashCode();


If your object has a composite logical key, return the hash of it's componants.
pre:
return CustomerId.GetHashCode() ^ ItemId.GetHashCode();
If your object has no logical key at all, get a new guid (only once, and store it), and return it's hash.

Dietrich fucked around with this message at 02:47 on Dec 21, 2011

wwb
Aug 17, 2004

On the whole implementing GetHashCode() overrides thing, is there any reason you all are using exponents? In most cases where I've done this and there were multiple values, I just concatenated all the values together in a big string and then called GetHashCode() on that.

adaz
Mar 7, 2009

wwb posted:

On the whole implementing GetHashCode() overrides thing, is there any reason you all are using exponents? In most cases where I've done this and there were multiple values, I just concatenated all the values together in a big string and then called GetHashCode() on that.

I've heard it explained before it is to get a better range of hashes which (somehow, I don't know) improves the hash lookups. Also, technet has a nice article on what you need to do when overriding equals & Hashcode (http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx).


e: for what it's worth the last time i needed to override getequals I was never able to get it quite right, so you know i'm probably wrong here.

e2: Yeppppppppp VVVVVVVVV

adaz fucked around with this message at 04:17 on Dec 21, 2011

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

wwb posted:

On the whole implementing GetHashCode() overrides thing, is there any reason you all are using exponents? In most cases where I've done this and there were multiple values, I just concatenated all the values together in a big string and then called GetHashCode() on that.

That's not an exponent, that's the xor operator. Bitwise operators, ahoy!

Dietrich
Sep 11, 2001

wwb posted:

On the whole implementing GetHashCode() overrides thing, is there any reason you all are using exponents? In most cases where I've done this and there were multiple values, I just concatenated all the values together in a big string and then called GetHashCode() on that.

Do not do that either. Concatenating strings in .net is a truck load of slow. Although this is less bad than the constant idea, it would only suck for you if you were trying to load a hash table with a large number of your objects, or compare your object with a large number of other objects or something.

epswing
Nov 4, 2003

Soiled Meat

Ithaqua posted:

All classes inherit from object. :confused:

rolleyes posted:

I know you're trying to get exactly this response to prove the point, but presumably he means it inherits directly from object with no intermediary class(es).

Funnily enough, one of the example for Equals on msdn explicitly subclasses Object.

code:
class Point: Object {
    ...
}

Dietrich
Sep 11, 2001

When you declare a class, and don't type : Object or : SomethingElse the compiler helpfully adds : Object for you.

boo_radley
Dec 30, 2005

Politeness costs nothing
What in the hell happened here? :psyduck:

Here's my two cents: If you override .Equals, and you're going to use your new class in a collection of some sort (or, iirc, serializing, or implementing one of several different types of interfaces) -- you owe it to yourself to implement .GetHashCode as well.

Hashes should be cheap to calculate (see Dietrich's warning against concatenating for what not to do), and echo the same logic as .Equals

For reference, see the MSDN page on the GetHashCode method. Although to be perfectly clear, I'm not sure why their third example uses constants for .GetHashCode. Seems like a bad way to illustrate the concept.

adaz
Mar 7, 2009

So a question that can come up (or at least I've had) - is say you have a class with an arbitrary number of properties as - say - strings, or an array in there or two. If you want to override equals to provide value equality between two objects of that same class what's your best bet? Because concatenating strings and then running GetHash() is apparently not efficient.

Sedro
Dec 31, 2008
There are a number of snags when implementing Equals/GetHashCode. To name a few:
- Equals not matching GetHashCode. For example, if Equals compares two strings case-insensitive, you should use a case-insensitive hash code.
- Mutable objects - always good to avoid them, but especially here. Mutating an object changes its hash, breaking anything that depends on the hash, like if the object was being used in a hash set.
- Subclassing can break the contract if you're not careful. See how the official examples use GetType() != obj.GetType(). If you don't do this, you can come up with cases where A.Equals(B) != B.Equals(A).

Worst of all, problems might only manifest in very specific circumstances.

adaz posted:

So a question that can come up (or at least I've had) - is say you have a class with an arbitrary number of properties as - say - strings, or an array in there or two. If you want to override equals to provide value equality between two objects of that same class what's your best bet? Because concatenating strings and then running GetHash() is apparently not efficient.
Your Equals should match your GetHashCode. If you compare 5 properties for equality, you should compose those same 5 properties into a hash code. The 5 combined values function as a composite key to the object.

You should be concerned if you're using too many/too complex properties as a key. You should think about what makes two instances equal. Must they have the exact same values in the array?

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

Sedro posted:

This advice is still valid. Returning a constant will result in a hash collision and fall back on Equals every time. See here. It's not much trouble to just implement it though.

No, it's terrible advice. You're right in the sense that it won't result in a Dictionary (or HashSet, or similar) suddenly returning incorrect answers, but they still won't function properly. Pretty much the entire point of using a Dictionary is its constant-time lookups, and by returning a constant value, you're breaking that behavior. Going from O(1) to O(n) is not a good thing.

adaz posted:

So a question that can come up (or at least I've had) - is say you have a class with an arbitrary number of properties as - say - strings, or an array in there or two. If you want to override equals to provide value equality between two objects of that same class what's your best bet? Because concatenating strings and then running GetHash() is apparently not efficient.

Sedro posted:

Your Equals should match your GetHashCode. If you compare 5 properties for equality, you should compose those same 5 properties into a hash code. The 5 combined values function as a composite key to the object.

Whenever I've needed to combine the hashes of multiple fields, I used this code, which (as far as I can remember) was taken from boost::hash_combine.

code:
public static int CombineHash(int seed, int hash)
{
  return unchecked(seed ^ (hash + -1640531527 + (seed << 6) + (seed >> 2)));
}
According to boost::hash_combine's documentation:
"Calls to hash_combine incrementally build the hash from the different members of point, it can be repeatedly called for any number of elements."

Dietrich
Sep 11, 2001

boo_radley posted:

I'm not sure why their third example uses constants for .GetHashCode. Seems like a bad way to illustrate the concept.

We need a :dice: for MSDN.

MSDN documentation is terrible.

wellwhoopdedooo
Nov 23, 2007

Pound Trooper!

Dietrich posted:

We need a :dice: for MSDN.

MSDN documentation is terrible.

Compared to what?

Admiral Snackbar
Mar 13, 2006

OUR SNEEZE SHIELDS CANNOT REPEL A HUNGER OF THAT MAGNITUDE
Wow, thanks for all the feedback! If I could, I'd like to run this by you folks to see if it's sufficient.

Suppose my class is called Boob, and it has two properties: CupSize and NippleSize, both of which are strings. My Equals() method would be:

code:
public override bool Equals(object obj)
{
    if (obj == null || GetType() != obj.GetType())
    {
        return false;
    }
    Boob b = (Boob)obj;
    return _cupSize == b.CupSize && _nippleSize == b.NippleSize;
}
(_cupSize and _nippleSize are private strings that are accessed by CupSize and NippleSize)

and my GetHashCode() would be:

code:
public override int GetHashCode()
{
    return _cupSize.GetHashCode() ^ _nippleSize.GetHashCode();
}
Is this enough?

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

Admiral Snackbar posted:

code:
public override int GetHashCode()
{
    return _cupSize.GetHashCode() ^ _nippleSize.GetHashCode();
}
Is this enough?

I'd generally advise against simply XORing hashes, because it can easily make hash collisions more likely. See wellwhoopdedooo's or my previous post for suggestions for combining hashes.

Dietrich
Sep 11, 2001

wellwhoopdedooo posted:

Compared to what?

C# In Depth. Written by one guy. Who doesn't even work in .net full time.

epswing
Nov 4, 2003

Soiled Meat

Admiral Snackbar posted:

code:
    return _cupSize == b.CupSize && _nippleSize == b.NippleSize;

You mentioned CupSize and NippleSize are strings, so that should be...

code:
    return _cupSize.Equals(b.CupSize) && _nippleSize.Equals(b.NippleSize);

http://msdn.microsoft.com/en-us/library/cc165449.aspx posted:

When you compare strings, you should use the methods that explicitly specify what kind of comparison you intend to perform. This makes your code much more maintainable and readable. Whenever possible, use the overloads of the methods of the System.String and System.Array classes that take a StringComparison enumeration parameter, so that you can specify which type of comparison to perform. It is best to avoid using the == and != operators when you compare strings. Also, avoid using the String.CompareTo instance methods because none of the overloads takes a StringComparison.

adaz
Mar 7, 2009

dwazegek posted:

No, it's terrible advice. You're right in the sense that it won't result in a Dictionary (or HashSet, or similar) suddenly returning incorrect answers, but they still won't function properly. Pretty much the entire point of using a Dictionary is its constant-time lookups, and by returning a constant value, you're breaking that behavior. Going from O(1) to O(n) is not a good thing.



Whenever I've needed to combine the hashes of multiple fields, I used this code, which (as far as I can remember) was taken from boost::hash_combine.

code:
public static int CombineHash(int seed, int hash)
{
  return unchecked(seed ^ (hash + -1640531527 + (seed << 6) + (seed >> 2)));
}
According to boost::hash_combine's documentation:
"Calls to hash_combine incrementally build the hash from the different members of point, it can be repeatedly called for any number of elements."

My C++ is non-existent but I want to make sure I'm understanding how this works, because overloading equals/hash code is something I will eventually need to do and I've always wanted to make sure I do it correctly.

From what I got here and looking at the boost documentation you start with an initial seed of 0, and the other parameter you are taking a hash value off of the values you're trying to combine. So, if you're using a string or something with .NET you could pass this the .GetHashCode() off the string with a seed of 0 and then move through each of the values you wish to combine using the supplied algorithm (which does some magic I don't really care about as long as it combines the hashes correctly).

Sound right?

Admiral Snackbar
Mar 13, 2006

OUR SNEEZE SHIELDS CANNOT REPEL A HUNGER OF THAT MAGNITUDE
Great - thanks everyone!

ljw1004
Jan 18, 2005

rum

Dietrich posted:

:ughh:

Do not do this. Never, ever do this.

On the contrary, returning a constant from GetHashCode is pretty reasonable:
http://blogs.msdn.com/b/jaredpar/archive/2008/06/03/making-equality-easier.aspx


But the most basic rule is: "Only calculate the hash code based off of primitive fields which are ReadOnly"
http://blogs.msdn.com/b/jaredpar/archive/2008/04/28/properly-implementing-equality-in-vb.aspx

dwazegek
Feb 11, 2005

WE CAN USE THIS :byodood:

epswing posted:

You mentioned CupSize and NippleSize are strings, so that should be...

code:
    return _cupSize.Equals(b.CupSize) && _nippleSize.Equals(b.NippleSize);

The (in)equality operators will just call .Equals themselves (or vice versa), so your example really isn't any different or better. I think the more important part of the quote is this part:

quote:

When you compare strings, you should use the methods that explicitly specify what kind of comparison you intend to perform.

So you should be using Equals(string, StringComparison) (or an equivalent comparer from the StringComparer class).


adaz posted:

Sound right?

Yep.

boo_radley
Dec 30, 2005

Politeness costs nothing

ljw1004 posted:

On the contrary, returning a constant from GetHashCode is pretty reasonable:
http://blogs.msdn.com/b/jaredpar/archive/2008/06/03/making-equality-easier.aspx

For a certain value of reasonable, I suppose. Jared's post is written from the perspective of satisfying a minimum base set of criteria for the BCL. He only addresses the performance hit after his sample:

quote:

Of course this does come with a trade off. As said before GetHashCode() is primarily used as a bucketing mechanism. It will cause the performance of bucketing collections such as Dictionary or Hashtable to drop from close to O(1) to O(N). But once again this is not a bug but a conscious trade off.

It's a bit perverse to say "this is the absolute bare minimum you really need to do to satisfy BCL" rather than helping people understand how to write performant code -- or at least write less terrible code. It might be making your fields read-only, or extending your class to account for mutable fields (ex. hash caching), but there has to be a better option than a static hash value.

No Pants
Dec 10, 2000

He's saying it's a design decision. If you aren't designing your class to be used in one of those collections, it's fine.

Adbot
ADBOT LOVES YOU

Dietrich
Sep 11, 2001

No Pants posted:

He's saying it's a design decision. If you aren't designing your class to be used in one of those collections, it's fine.

I too enjoy having to make sure that the GetHashCode implementation is not poo poo every time I use a class in a collection.

If you're writing a throw away test class, sure. If you're writing anything else, just take the extra half a second and return the hash code of the logical key.

  • Locked thread