2016-07-10 19 views
0

Ich habe WndProc(Message m) Override. Dies wird offensichtlich viel genannt. Nehmen wir an, ich möchte, dass einige Nachrichten als "behandelt" markiert werden. Also sollte ich Result auf 1 setzen. Aber Result Eigentum ist IntPtr. Was passiert, wenn m.Result = new IntPtr(1) ausgeführt wird? Jeder Anruf würde Speicher für einen Int32 Wert zuweisen? Was würde passieren, wenn ich eine statische IntPtr Variable erstellen und sie auf new IntPtr(1) setzen würde?C#: WndProc() - und IntPtr-Typen - wie wird damit richtig umgegangen? Ist der IntPtr-Typ besonders zu pflegen?

Was ist der richtigste Weg, dies zu tun?

Dann möchte ich m.LParam zu bekannten Wert zu vergleichen. Es ist auch IntPtr und ich kann es mehrere Möglichkeiten:

if (m.LParam == (IntPtr)0x0001) ... 
if ((int)m.LParam == 0x0001) ... 
if (m.LParam == myStaticIntPtr1) ... 

Was die Kosten für solche Vergleiche? Was passiert auf niedrigem Niveau während der obigen 3? Message Typ ist nicht verfügbar. Also ich denke ich kann es sicher übergehen, es an base.WndProc() zu übergeben, habe ich recht? Nichts muss damit getan werden, wenn ich nur die Nachricht verwerfen möchte?

Bonus Frage: Ich bin nicht sicher, aber ich glaube, ich DllImport s auf pinvoke.net gesehen habe, wo IntPtr s in MSDN-Dokumentation nur int s verändert wurden. Möglich? Funktioniert es? Was geschieht? Implizite Konvertierung?

BTW, ist IntPtr ein verwalteten Typ, nicht wahr? Also, wenn ich keinen unmanaged Code nenne oder Einweg-Typen verwende - keine Notwendigkeit, etwas zu entsorgen?

+2

Sie sind * massiv * dies zu überdenken. Dies sind eingebaute, grundlegende Typen; Speicherzuweisung ist nicht teuer. Außerdem legen Sie in diesem Fall den Wert eines Felds in einer Struktur fest, sodass der Speicher bereits zugewiesen wurde. All diese Operationen sind praktisch kostenlos.Und sie sind alle in Bezug auf die Leistung gleichwertig. Ziehen Sie Semantisch lieber Casting-Konstanten als IntPtr, anstatt IntPtrs auf Ints zu setzen. –

+0

IntPtr ist eine 32-Bit-Ganzzahl, die auf ein nicht verwaltetes Objekt verweist. Das nicht verwaltete Objekt befindet sich im gemeinsam genutzten Speicher (statisch) und befindet sich nicht wie verwaltete Objekte im Ausführungsstapel. Es sollte keinen Unterschied machen, wenn Sie IntPtr oder int verwenden, außer ein Zeiger ist nicht signiert, so dass Uint besser wäre. (IntPtr) 0x0001 macht keinen Sinn, da es auf Speicherplatz 0x0001 zeigen würde. – jdweng

+1

Außerdem haben Sie hier zu viele Fragen in einer Frage gestellt. Versuche, einige dieser Fragen kurz zu beantworten ... nein, du solltest immer Nachrichten an die Fensterprozedur der Basisklasse weiterleiten. Nein, DllImport-Signaturen, die int für Zeigertypen verwenden, sind falsch und fehlerhaft; Tu das nicht. Ja, IntPtr ist ein verwalteter Typ, aber der CLR-Marshaller erkennt ihn und marschiert solche Werte ordnungsgemäß als Zeiger. Sie sind jedoch immer noch Zeiger auf nicht verwaltete Objekte, daher müssen diese nicht verwalteten Objekte entsorgt/gelöscht/freigegeben/geschlossen werden, wie es die Dokumentation erfordert. –

Antwort

1

IntPtr ein Werttyp ist, und nicht jeden Speicherzuweisung nicht entstehen - es ist entweder auf dem Stack oder einen Teil einer anderen Speicherstruktur Typ. In C# wird der Operator new sowohl für Wert- als auch für Referenztypen verwendet, was bei einem C++ - Hintergrund verwirrend sein kann. Sie können sogar schreiben new int() und wieder wird es keine Zuordnung geben.

Darüber hinaus ist es mit einem Int32 (int in C#) Gießen können falsche Ergebnisse liefern - in einem 64-Bit-Prozess wird die Größe eines Int64 sein (man kann IntPtr.Size überprüfen).

Kurz gesagt, die Kosten für den Vergleich ist vernachlässigbar - es ist das gleiche wie den Vergleich zweier Ganzzahlen. Sie können die IntPtr s in statischen Feldern behalten, wenn dies die Lesbarkeit verbessert, aber Sie sollten sich nicht um den Speicher kümmern.

Die folgenden sind äquivalent:

  • new IntPtr(1)
  • (IntPtr)1 - es ist ein expliziter Cast-Operator, der es den obigen Konstruktor übersetzt

Der Grund, diese Art ist weg zu abstrahieren besteht die Größe eines Zeigers im Umgang mit nicht verwalteten APIs, sodass Sie in 32- und 64-Bit-Prozessen in Win32 P/Invoke ausführen können.