Share via


Varsayılan Sıralama Davranışı

Birlikte çalışma hazırlama, yöntem parametreleriyle ilişkili verilerin yönetilen ve yönetilmeyen bellek arasında geçerken nasıl davranacağını belirleyen kurallar üzerinde çalışır. Bu yerleşik kurallar veri türü dönüştürmeleri gibi sıralama etkinliklerini, çağıranın geçirilen verileri değiştirip değiştiremeyeceğini ve bu değişiklikleri çağırana döndürebileceğini ve hangi koşullarda marshaller'ın performans iyileştirmeleri sağladığını denetler.

Bu bölümde birlikte çalışma marshalling hizmetinin varsayılan davranışsal özellikleri tanımlanır. Diziler, Boole türleri, karakter türleri, temsilciler, sınıflar, nesneler, dizeler ve yapılar hakkında ayrıntılı bilgiler sunar.

Not

Genel türlerin yapılandırılması desteklenmez. Daha fazla bilgi için bkz . Genel Türleri Kullanarak Birlikte Çalışma.

Birlikte çalışma yardımcısı ile bellek yönetimi

Birlikte çalışma marshaller her zaman yönetilmeyen kod tarafından ayrılan belleği boşaltmaya çalışır. Bu davranış COM bellek yönetimi kurallarıyla uyumlu olsa da yerel C++'ı yöneten kurallardan farklıdır.

Platform çağrısı kullanılırken yerel C++ davranışını (bellek boşaltma olmadan) tahmin ederseniz karışıklık oluşabilir ve bu da işaretçiler için belleği otomatik olarak boşaltabilir. Örneğin, C++ DLL'den aşağıdaki yönetilmeyen yöntemi çağırmak hiçbir belleği otomatik olarak boşaltmaz.

Yönetilmeyen imza

BSTR MethodOne (BSTR b) {  
     return b;  
}  

Ancak, yöntemini bir platform çağırma prototipi olarak tanımlarsanız, her BSTR türünü bir String türle değiştirin ve ortak MethodOnedil çalışma zamanı iki kez boşaltmaya b çalışır. Dize türleri yerine türleri kullanarak IntPtr sıralama davranışını değiştirebilirsiniz.

Çalışma zamanı, belleği boşaltmak için her zaman Windows'ta CoTaskMemFree yöntemini ve diğer platformlarda ücretsiz yöntemini kullanır. Üzerinde çalıştığınız bellek Windows'ta CoTaskMemAlloc yöntemiyle veya diğer platformlarda malloc yöntemiyle ayrılmadıysa, intPtr kullanmanız ve uygun yöntemi kullanarak belleği el ile boşaltmanız gerekir. Benzer şekilde, çekirdek belleğine bir işaretçi döndüren Kernel32.dll GetCommandLine işlevini kullanırken olduğu gibi, belleğin hiçbir zaman boşaltılmaması gereken durumlarda otomatik bellek boşaltmayı önleyebilirsiniz. Belleği el ile boşaltma hakkında ayrıntılı bilgi için bkz . Arabellek örneği.

Sınıflar için varsayılan sıralama

Sınıflar yalnızca COM birlikte çalışma tarafından sıralanabilir ve her zaman arabirim olarak sıralanır. Bazı durumlarda sınıfını sıralamak için kullanılan arabirim, sınıf arabirimi olarak bilinir. Sınıf arabirimini seçtiğiniz bir arabirimle geçersiz kılma hakkında bilgi için bkz . Sınıf arabirimini tanıtma.

Sınıfları COM'a Geçirme

Yönetilen bir sınıf COM'a geçirildiğinde, birlikte çalışma marshaller sınıfı otomatik olarak bir COM proxy'si ile sarmalar ve ara sunucu tarafından üretilen sınıf arabirimini COM yöntemi çağrısına geçirir. Ardından proxy, sınıf arabirimindeki tüm çağrıları yönetilen nesneye geri gönderir. Proxy ayrıca sınıfı tarafından açıkça uygulanmayan diğer arabirimleri de kullanıma sunar. Ara sunucu, sınıf adına IUnknown ve IDispatch gibi arabirimleri otomatik olarak uygular.

Sınıfları .NET Code'a Geçirme

Ortak sınıflar genellikle COM'da yöntem bağımsız değişkenleri olarak kullanılmaz. Bunun yerine, genellikle ortak sınıf yerine varsayılan bir arabirim geçirilir.

Bir arabirim yönetilen koda geçirildiğinde, birlikte çalışma sıralayıcısı arabirimi uygun sarmalayıcıyla sarmalamaktan ve sarmalayıcıyı yönetilen yönteme geçirmekten sorumludur. Hangi sarmalayıcının kullanılacağını belirlemek zor olabilir. Bir COM nesnesinin her örneği, nesnenin kaç arabirim uyguladığı fark etmez, tek, benzersiz bir sarmalayıcıya sahiptir. Örneğin, beş ayrı arabirim uygulayan tek bir COM nesnesi yalnızca bir sarmalayıcıya sahiptir. Aynı sarmalayıcı beş arabirimin tümünü de kullanıma sunar. COM nesnesinin iki örneği oluşturulursa sarmalayıcının iki örneği oluşturulur.

Sarmalayıcının yaşam süresi boyunca aynı türe sahip olması için, birlikte çalışma başlatıcısı, nesne tarafından kullanıma sunulan bir arabirim ilk kez marshaller aracılığıyla geçirildiğinde doğru sarmalayıcıyı tanımlamalıdır. Marshaller, nesnenin uyguladığı arabirimlerden birine bakarak nesneyi tanımlar.

Örneğin, marshaller yönetilen koda geçirilen arabirimi sarmalamak için sınıf sarmalayıcının kullanılması gerektiğini belirler. Arabirim, marshaller aracılığıyla ilk geçirildiğinde, marshaller arabirimin bilinen bir nesneden gelip gelmediğini denetler. Bu denetim iki durumda gerçekleşir:

  • Arabirim, başka bir yerde COM'a geçirilen başka bir yönetilen nesne tarafından uygulanıyor. Marshaller, yönetilen nesneler tarafından kullanıma sunulan arabirimleri kolayca tanımlayabilir ve arabirimi uygulamayı sağlayan yönetilen nesneyle eşleştirebilir. Ardından yönetilen nesne yöntemine geçirilir ve sarmalayıcı gerekmez.

  • Zaten sarmalanmış bir nesne arabirimini uyguluyor. Bu durumun söz konusu olup olmadığını belirlemek için, marshaller nesnesini IUnknown arabirimi için sorgular ve döndürülen arabirimi zaten sarmalanmış olan diğer nesnelerin arabirimleriyle karşılaştırır. Arabirim başka bir sarmalayıcıyla aynıysa, nesneler aynı kimliğe sahiptir ve mevcut sarmalayıcı yöntemine geçirilir.

Arabirim bilinen bir nesneden değilse, marshaller aşağıdakileri yapar:

  1. Marshaller, IProvideClassInfo2 arabirimi için nesnesini sorgular. Sağlanırsa, marshaller arabirimi sağlayan ortak sınıfı tanımlamak için IProvideClassInfo2.GetGUID'den döndürülen CLSID'yi kullanır. CLSID ile, derleme daha önce kaydedilmişse, marshaller sarmalayıcıyı kayıt defterinden bulabilir.

  2. Marshaller, IProvideClassInfo arabirimi için arabirimi sorgular. Sağlanırsa, marshaller arabirimini ortaya çıkartan sınıfın CLSID'sini belirlemek için IProvideClassInfo.GetClassinfo'dan döndürülen ITypeInfo'yu kullanır. Marshaller sarmalayıcının meta verilerini bulmak için CLSID'yi kullanabilir.

  3. Marshaller hala sınıfını tanımlayamıyorsa, arabirimini System.__ComObject adlı genel bir sarmalayıcı sınıfıyla sarmalar.

Temsilciler için varsayılan sıralama

Yönetilen temsilci, çağrı mekanizmasına göre COM arabirimi veya işlev işaretçisi olarak sıralanır:

  • Platform çağrısı için, temsilci varsayılan olarak yönetilmeyen işlev işaretçisi olarak sıralanır.

  • COM birlikte çalışma için, temsilci varsayılan olarak _Delegate türünde bir COM arabirimi olarak sıralanır. _Delegate arabirimi Mscorlib.tlb tür kitaplığında tanımlanır ve temsilcinin Delegate.DynamicInvoke başvuracağı yöntemi çağırmanızı sağlayan yöntemini içerir.

Aşağıdaki tabloda yönetilen temsilci veri türü için sıralama seçenekleri gösterilmektedir. özniteliği, MarshalAsAttribute temsilcileri sıralamak için birkaç UnmanagedType numaralandırma değeri sağlar.

Numaralandırma türü Yönetilmeyen biçimin açıklaması
UnmanagedType.FunctionPtr Yönetilmeyen işlev işaretçisi.
UnmanagedType.Interface Mscorlib.tlb dosyasında tanımlandığı gibi _Delegate türünde bir arabirim.

Yöntemlerinin DelegateTestInterface com türü kitaplığına aktarıldığı aşağıdaki örnek kodu göz önünde bulundurun. Yalnızca ref (veya ByRef) anahtar sözcüğüyle işaretlenmiş temsilcilerin In/Out parametreleri olarak geçirildiğini unutmayın.

using System;  
using System.Runtime.InteropServices;  
  
public interface DelegateTest {  
void m1(Delegate d);  
void m2([MarshalAs(UnmanagedType.Interface)] Delegate d);
void m3([MarshalAs(UnmanagedType.Interface)] ref Delegate d);
void m4([MarshalAs(UnmanagedType.FunctionPtr)] Delegate d);
void m5([MarshalAs(UnmanagedType.FunctionPtr)] ref Delegate d);
}  

Tür kitaplığı gösterimi

importlib("mscorlib.tlb");  
interface DelegateTest : IDispatch {  
[id(…)] HRESULT m1([in] _Delegate* d);  
[id(…)] HRESULT m2([in] _Delegate* d);  
[id(…)] HRESULT m3([in, out] _Delegate** d);  
[id()] HRESULT m4([in] int d);  
[id()] HRESULT m5([in, out] int *d);  
   };  

Bir işlev işaretçisi, diğer yönetilmeyen işlev işaretçilerinin başvurusu kaldırılabildiği gibi başvurulabilir.

Bu örnekte, iki temsilci olarak UnmanagedType.FunctionPtrsıralandığında, sonuç bir int ve işaretçisidir int. Temsilci türleri sıraya alındığından, int burada bellekteki temsilcinin adresi olan bir void ()void* işaretçisini temsil eder. Başka bir deyişle, bu sonuç 32 bit Windows sistemlerine özgüdür, çünkü int burada işlev işaretçisinin boyutu gösterilir.

Not

Yönetilmeyen kod tarafından tutulan yönetilen bir temsilciye yönelik işlev işaretçisi başvurusu, ortak dil çalışma zamanının yönetilen nesnede çöp toplama gerçekleştirmesini engellemez.

Örneğin, aşağıdaki kod yanlıştır çünkü yöntemine cb geçirilen nesneye SetChangeHandler başvuru yöntemin ömrünün Test ötesinde canlı tutmazcb. cb Nesne çöp olarak toplandıktan sonra, geçirilen SetChangeHandler işlev işaretçisi artık geçerli olmaz.

public class ExternalAPI {  
   [DllImport("External.dll")]  
   public static extern void SetChangeHandler(  
      [MarshalAs(UnmanagedType.FunctionPtr)]ChangeDelegate d);  
}  
public delegate bool ChangeDelegate([MarshalAs(UnmanagedType.LPWStr) string S);  
public class CallBackClass {  
   public bool OnChange(string S){ return true;}  
}  
internal class DelegateTest {  
   public static void Test() {  
      CallBackClass cb = new CallBackClass();  
      // Caution: The following reference on the cb object does not keep the
      // object from being garbage collected after the Main method
      // executes.  
      ExternalAPI.SetChangeHandler(new ChangeDelegate(cb.OnChange));
   }  
}  

Beklenmeyen çöp toplamayı telafi etmek için çağıranın, yönetilmeyen işlev işaretçisi kullanımda olduğu sürece nesnenin canlı tutulduğundan emin olması cb gerekir. İsteğe bağlı olarak, aşağıdaki örnekte gösterildiği gibi, yönetilmeyen kodun artık işlev işaretçisine gerek kalmadığında yönetilen kodu bildirmesini sağlayabilirsiniz.

internal class DelegateTest {  
   CallBackClass cb;  
   // Called before ever using the callback function.  
   public static void SetChangeHandler() {  
      cb = new CallBackClass();  
      ExternalAPI.SetChangeHandler(new ChangeDelegate(cb.OnChange));  
   }  
   // Called after using the callback function for the last time.  
   public static void RemoveChangeHandler() {  
      // The cb object can be collected now. The unmanaged code is
      // finished with the callback function.  
      cb = null;  
   }  
}  

Değer türleri için varsayılan sıralama

Tamsayılar ve kayan noktalı sayılar gibi çoğu değer türü blittable'dır ve sıralama gerektirmez. Diğer bölünebilir olmayan türlerin yönetilen ve yönetilmeyen bellekte benzeri olmayan gösterimleri vardır ve bunlar için marshalling gerekir. Yine de diğer türler, birlikte çalışma sınırı boyunca açık biçimlendirme gerektirir.

Bu bölüm, aşağıdaki biçimlendirilmiş değer türleri hakkında bilgi sağlar:

Bu konu, biçimlendirilmiş türleri açıklamaya ek olarak sıra dışı sıralama davranışına sahip Sistem Değeri Türlerini tanımlar.

Biçimlendirilmiş tür, bellekteki üyelerinin düzenini açıkça denetleyen bilgiler içeren karmaşık bir türdür. Üye düzeni bilgileri özniteliği kullanılarak StructLayoutAttribute sağlanır. Düzen aşağıdaki LayoutKind numaralandırma değerlerinden biri olabilir:

  • LayoutKind.Auto

    Ortak dil çalışma zamanının, etkinlik için türün üyelerini yeniden sıralamak için serbest olduğunu gösterir. Ancak, yönetilmeyen koda bir değer türü geçirildiğinde, üyelerin düzeni tahmin edilebilir. Böyle bir yapıyı otomatik olarak hazırlama girişimi bir özel duruma neden olur.

  • LayoutKind.Sequential

    Türün üyelerinin yönetilmeyen bellekte yönetilen tür tanımında göründükleri sırayla yerleştirileceklerini gösterir.

  • LayoutKind.Explicit

    Üyelerin her alanla sağlanana FieldOffsetAttribute göre düzenlendiğini gösterir.

Platform Çağırmada Kullanılan Değer Türleri

Aşağıdaki örnekte Point ve Rect türleri, StructLayoutAttribute kullanarak üye düzeni bilgilerini sağlar.

Imports System.Runtime.InteropServices  
<StructLayout(LayoutKind.Sequential)> Public Structure Point  
   Public x As Integer  
   Public y As Integer  
End Structure  
<StructLayout(LayoutKind.Explicit)> Public Structure Rect  
   <FieldOffset(0)> Public left As Integer  
   <FieldOffset(4)> Public top As Integer  
   <FieldOffset(8)> Public right As Integer  
   <FieldOffset(12)> Public bottom As Integer  
End Structure  
using System.Runtime.InteropServices;  
[StructLayout(LayoutKind.Sequential)]  
public struct Point {  
   public int x;  
   public int y;  
}
  
[StructLayout(LayoutKind.Explicit)]  
public struct Rect {  
   [FieldOffset(0)] public int left;  
   [FieldOffset(4)] public int top;  
   [FieldOffset(8)] public int right;  
   [FieldOffset(12)] public int bottom;  
}  

Yönetilmeyen koda sıralandığında, bu biçimlendirilmiş türler C stili yapılar olarak sıralanır. Bu, yapı bağımsız değişkenleri olan yönetilmeyen bir API'yi çağırmanın kolay bir yolunu sağlar. Örneğin, POINT ve RECT yapıları Aşağıdaki gibi Microsoft Windows API PtInRect işlevine geçirilebilir:

BOOL PtInRect(const RECT *lprc, POINT pt);  

Aşağıdaki platform çağırma tanımını kullanarak yapıları geçirebilirsiniz:

Friend Class NativeMethods
    Friend Declare Auto Function PtInRect Lib "User32.dll" (
        ByRef r As Rect, p As Point) As Boolean
End Class
internal static class NativeMethods
{
   [DllImport("User32.dll")]
   internal static extern bool PtInRect(ref Rect r, Point p);
}

Rect Yönetilmeyen API işleve geçirilecek bir işaretçi beklediğinden RECT değer türü başvuruya göre geçirilmelidir. Point Yönetilmeyen API'nin yığına geçirilmesini beklediğinden POINT değer türü değere göre geçirilir. Bu ince fark çok önemlidir. Başvurular yönetilmeyen koda işaretçi olarak geçirilir. Değerler yığındaki yönetilmeyen koda geçirilir.

Not

Biçimlendirilmiş bir tür yapı olarak sıralandığında, yalnızca türün içindeki alanlara erişilebilir. Türün yöntemleri, özellikleri veya olayları varsa yönetilmeyen koddan erişilemez.

Sınıflar, sabit üye düzenine sahip olmaları koşuluyla, yönetilmeyen kodlara C stili yapılar olarak da sıralanabilir. Sınıfın üye düzeni bilgileri de özniteliğiyle birlikte StructLayoutAttribute sağlanır. Sabit düzen içeren değer türleri ile sabit düzenli sınıflar arasındaki temel fark, yönetilmeyen koda göre düzenlenme şeklidir. Değer türleri değere (yığında) göre geçirilir ve sonuç olarak çağıran tarafından türün üyelerinde yapılan değişiklikler çağıran tarafından görülmez. Başvuru türleri başvuruya göre geçirilir (yığında türe bir başvuru geçirilir); sonuç olarak, çağıran tarafından bir türün blittable türü üyelerinde yapılan tüm değişiklikler arayan tarafından görülür.

Not

Bir başvuru türü, bölünebilir olmayan türlerin üyelerine sahipse, dönüştürme iki kez gereklidir: bağımsız değişken yönetilmeyen tarafa ilk kez geçirildiğinde ve ikinci kez çağrıdan döndürüldüyse. Bu ek yük nedeniyle, çağıran tarafından yapılan değişiklikleri görmek istiyorsa, bir bağımsız değişkene Açıkça Giriş/Çıkış parametreleri uygulanmalıdır.

Aşağıdaki örnekte, SystemTime sınıfı sıralı üye düzenine sahiptir ve Windows API GetSystemTime işlevine geçirilebilir.

<StructLayout(LayoutKind.Sequential)> Public Class SystemTime  
   Public wYear As System.UInt16  
   Public wMonth As System.UInt16  
   Public wDayOfWeek As System.UInt16  
   Public wDay As System.UInt16  
   Public wHour As System.UInt16  
   Public wMinute As System.UInt16  
   Public wSecond As System.UInt16  
   Public wMilliseconds As System.UInt16  
End Class  
[StructLayout(LayoutKind.Sequential)]  
   public class SystemTime {  
   public ushort wYear;
   public ushort wMonth;  
   public ushort wDayOfWeek;
   public ushort wDay;
   public ushort wHour;
   public ushort wMinute;
   public ushort wSecond;
   public ushort wMilliseconds;
}  

GetSystemTime işlevi aşağıdaki gibi tanımlanır:

void GetSystemTime(SYSTEMTIME* SystemTime);  

GetSystemTime için eşdeğer platform çağırma tanımı aşağıdaki gibidir:

Friend Class NativeMethods
    Friend Declare Auto Sub GetSystemTime Lib "Kernel32.dll" (
        ByVal sysTime As SystemTime)
End Class
internal static class NativeMethods
{
   [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
   internal static extern void GetSystemTime(SystemTime st);
}

Bağımsız değişkenin SystemTime bir değer türü değil, bir sınıf olduğundan SystemTime başvuru bağımsız değişkeni olarak yazılmadığına dikkat edin. Değer türlerinden farklı olarak, sınıflar her zaman başvuruyla geçirilir.

Aşağıdaki kod örneğinde adlı SetXYbir yöntemi olan farklı Point bir sınıf gösterilmektedir. Türün sıralı düzeni olduğundan yönetilmeyen koda geçirilebilir ve yapı olarak sıralanabilir. Ancak, SetXY nesne başvuruyla geçirilse bile üye yönetilmeyen koddan çağrılamaz.

<StructLayout(LayoutKind.Sequential)> Public Class Point  
   Private x, y As Integer  
   Public Sub SetXY(x As Integer, y As Integer)  
      Me.x = x  
      Me.y = y  
   End Sub  
End Class  
[StructLayout(LayoutKind.Sequential)]  
public class Point {  
   int x, y;  
   public void SetXY(int x, int y){
      this.x = x;  
      this.y = y;  
   }  
}  

COM Birlikte Çalışmasında Kullanılan Değer Türleri

Biçimlendirilmiş türler COM birlikte çalışma yöntemi çağrılarına da geçirilebilir. Aslında, bir tür kitaplığına aktarıldığında, değer türleri otomatik olarak yapılara dönüştürülür. Aşağıdaki örnekte gösterildiği gibi, Point değer türü adlı Pointbir tür tanımına (typedef) dönüşür. Tür kitaplığının Point başka bir yerindeki değer türüne yapılan tüm başvurular typedef ile Point değiştirilir.

Tür kitaplığı gösterimi

typedef struct tagPoint {  
   int x;  
   int y;  
} Point;  
interface _Graphics {  
   …  
   HRESULT SetPoint ([in] Point p)  
   HRESULT SetPointRef ([in,out] Point *p)  
   HRESULT GetPoint ([out,retval] Point *p)  
}  

COM arabirimleri aracılığıyla sıralama yaparken değerleri ve platform çağırma çağrılarına yapılan başvuruları sıralamak için kullanılan kuralların aynısı kullanılır. Örneğin, değer türünün bir örneği Point .NET Framework'ten COM'a geçirildiğinde, Point değeri tarafından geçirilir. Point Değer türü başvuruyla geçirilirse, yığında bir Point işaretçisi geçirilir. Birlikte çalışma marshaller, her iki yönde de daha yüksek düzeydeki dolaylı işlemleri (Nokta **) desteklemez.

Not

LayoutKind Dışarı aktarılan tür kitaplığı açık bir düzeni ifade edemeyeceğinden, numaralandırma değerinin Açık olarak ayarlandığı yapılar COM birlikte çalışmasında kullanılamaz.

Sistem Değer Türleri

Ad System alanı, çalışma zamanı temel türlerinin kutulanmış biçimini temsil eden birkaç değer türüne sahiptir. Örneğin, değer türü System.Int32 yapısı ELEMENT_TYPE_I4 kutulu biçimini temsil eder. Diğer biçimlendirilmiş türler gibi bu türleri yapı olarak sıralamak yerine, bunları kutuladıkları ilkel türler gibi sıralarsınız. Bu nedenle System.Int32, long türünde tek bir üye içeren bir yapı yerine ELEMENT_TYPE_I4 olarak sıralanır. Aşağıdaki tabloda, Sistem ad alanında ilkel türlerin kutulanmış gösterimleri olan değer türlerinin listesi yer alır.

Sistem değer türü Öğe türü
System.Boolean ELEMENT_TYPE_BOOLEAN
System.SByte ELEMENT_TYPE_I1
System.Byte ELEMENT_TYPE_UI1
System.Char ELEMENT_TYPE_CHAR
System.Int16 ELEMENT_TYPE_I2
System.UInt16 ELEMENT_TYPE_U2
System.Int32 ELEMENT_TYPE_I4
System.UInt32 ELEMENT_TYPE_U4
System.Int64 ELEMENT_TYPE_I8
System.UInt64 ELEMENT_TYPE_U8
System.Single ELEMENT_TYPE_R4
System.Double ELEMENT_TYPE_R8
System.String ELEMENT_TYPE_STRING
System.IntPtr ELEMENT_TYPE_I
System.UIntPtr ELEMENT_TYPE_U

Sistem ad alanı içindeki diğer bazı değer türleri farklı şekilde işlenir. Yönetilmeyen kodun bu türler için zaten iyi oluşturulmuş biçimleri olduğundan, sıralayıcının bunları sıralamak için özel kuralları vardır. Aşağıdaki tabloda, Sistem ad alanında özel değer türleri ve bunların sıralandığı yönetilmeyen tür listelenmiştir.

Sistem değer türü IDL türü
System.DateTime DATE
System.Decimal ON -DA -LIK
System.Guid GUID
System.Drawing.Color OLE_COLOR

Aşağıdaki kod, Stdole2 tür kitaplığında DATE, GUID, DECIMAL ve OLE_COLOR yönetilmeyen türlerin tanımını gösterir.

Tür kitaplığı gösterimi

typedef double DATE;  
typedef DWORD OLE_COLOR;  
  
typedef struct tagDEC {  
    USHORT    wReserved;  
    BYTE      scale;  
    BYTE      sign;  
    ULONG     Hi32;  
    ULONGLONG Lo64;  
} DECIMAL;  
  
typedef struct tagGUID {  
    DWORD Data1;  
    WORD  Data2;  
    WORD  Data3;  
    BYTE  Data4[ 8 ];  
} GUID;  

Aşağıdaki kod, yönetilen IValueTypes arabirimde karşılık gelen tanımları gösterir.

Public Interface IValueTypes  
   Sub M1(d As System.DateTime)  
   Sub M2(d As System.Guid)  
   Sub M3(d As System.Decimal)  
   Sub M4(d As System.Drawing.Color)  
End Interface  
public interface IValueTypes {  
   void M1(System.DateTime d);  
   void M2(System.Guid d);  
   void M3(System.Decimal d);  
   void M4(System.Drawing.Color d);  
}  

Tür kitaplığı gösterimi

[…]  
interface IValueTypes : IDispatch {  
   HRESULT M1([in] DATE d);  
   HRESULT M2([in] GUID d);  
   HRESULT M3([in] DECIMAL d);  
   HRESULT M4([in] OLE_COLOR d);  
};  

Ayrıca bkz.