Desen tabanlı fixed deyimiPattern-based fixed statement

ÖzetSummary

Türlerin deyimlere katılmasını sağlayacak bir model ortaya çıkarabilir fixed .Introduce a pattern that would allow types to participate in fixed statements.

MotivasyonMotivation

Dil, yönetilen verileri sabitleme ve temel alınan arabelleğe yerel bir işaretçi alma mekanizması sağlar.The language provides a mechanism for pinning managed data and obtain a native pointer to the underlying buffer.

fixed(byte* ptr = byteArray)
{
   // ptr is a native pointer to the first element of the array
   // byteArray is protected from being moved/collected by the GC for the duration of this block 
}

' De katılabilen türlerin kümesi, fixed dizilerle ve bunlarla sınırlandırılmıştır System.String .The set of types that can participate in fixed is hardcoded and limited to arrays and System.String. "Özel" türler, gibi yeni temel öğeler ImmutableArray<T> Span<T> Utf8String tanıtıldığında ölçeklenmez.Hardcoding "special" types does not scale when new primitives such as ImmutableArray<T>, Span<T>, Utf8String are introduced.

Ayrıca, için geçerli çözüm System.String bir oldukça rigıd API 'sine dayanır.In addition, the current solution for System.String relies on a fairly rigid API. API 'nin şekli, System.String UTF16 kodlu verileri nesne başlığından sabit bir uzaklığa katıştıran bitişik bir nesne olduğunu gösterir.The shape of the API implies that System.String is a contiguous object that embeds UTF16 encoded data at a fixed offset from the object header. Bu yaklaşım, temeldeki düzende değişiklik gerektirebilecek çeşitli tekliflerde sorun bulmuştur.Such approach has been found problematic in several proposals that could require changes to the underlying layout. System.StringYönetilmeyen birlikte çalışma amacıyla kendi iç gösteriminden daha esnek bir şekilde geçiş yapabilmesi istenebilir.It would be desirable to be able to switch to something more flexible that decouples System.String object from its internal representation for the purpose of unmanaged interop.

Ayrıntılı tasarımDetailed design

DesenPattern

Uygun bir model tabanlı "fixed" gereksinimi şunlar için gereklidir:A viable pattern-based “fixed” need to:

  • Örneği sabitlemek için yönetilen başvuruları sağlayın ve işaretçiyi başlatın (tercihen bu aynı başvurudur)Provide the managed references to pin the instance and to initialize the pointer (preferably this is the same reference)
  • Yönetilmeyen öğenin türünü ("String" için "Char") kesin bir şekilde iletinConvey unambiguously the type of the unmanaged element (i.e. “char” for “string”)
  • Başvurabileceğiniz bir şey olmadığında "boş" durumunda davranış göstermelidir.Prescribe the behavior in "empty" case when there is nothing to refer to.
  • API yazarları, türü dışında kullanımını engelleyen tasarım kararlarına doğru göndermemelidir fixed .Should not push API authors toward design decisions that hurt the use of the type outside of fixed.

Yukarıdaki bir başvuru döndüren üyenin tanınması için yukarıdaki ref [readonly] T GetPinnableReference()I think the above could be satisfied by recognizing a specially named ref-returning member: ref [readonly] T GetPinnableReference().

Deyimin kullanılabilmesi için fixed aşağıdaki koşulların karşılanması gerekir:In order to be used by the fixed statement the following conditions must be met:

  1. Bir tür için yalnızca bir tane belirtilen üye vardır.There is only one such member provided for a type.
  2. Veya ile ref döndürür ref readonly .Returns by ref or ref readonly. ( readonly sabit/salt okunur türlerin yazarları, türü, güvenli kodda kullanılabilen YAZıLABILIR API eklemeden uygulayabilir)(readonly is permitted so that authors of immutable/readonly types could implement the pattern without adding writeable API that could be used in safe code)
  3. T, yönetilmeyen bir türdür.T is an unmanaged type. (çünkü T* işaretçi türü olur.(since T* becomes the pointer type. Kısıtlama, "yönetilmeyen" kavramı genişletilmişse doğal olarak genişletilir.The restriction will naturally expand if/when the notion of "unmanaged" is expanded)
  4. nullptrSabitlemeye veri olmadığında, büyük olasılıkla empest 'yi almanın mümkün olduğu durumlarda yönetilen döndürür.Returns managed nullptr when there is no data to pin – probably the cheapest way to convey emptiness. (dizeler null sonlandırıldığı için "" dizesinin ' \ 0 ' öğesine bir başvuru döndürdüğünü unutmayın)(note that “” string returns a ref to '\0' since strings are null-terminated)

Bunun için alternatif olarak, #3 boş durumlarda sonucun tanımsız veya uygulamaya özgü olması için izin verebilir.Alternatively for the #3 we can allow the result in empty cases be undefined or implementation-specific. Bununla birlikte, API 'nin daha tehlikeli ve uygunsuz uyumluluk ve istenmeyen uyumlulukta olması olabilir.That, however, may make the API more dangerous and prone to abuse and unintended compatibility burdens.

ÇeviriTranslation

fixed(byte* ptr = thing)
{ 
    // <BODY>
}

Aşağıdaki sözde kod olur (C# ' ta ifade edilemez)becomes the following pseudocode (not all expressible in C#)

byte* ptr;
// specially decorated "pinned" IL local slot, not visible to user code.
pinned ref byte _pinned;

try
{
    // NOTE: null check is omitted for value types 
    // NOTE: `thing` is evaluated only once (temporary is introduced if necessary) 
    if (thing != null)
    {
        // obtain and "pin" the reference
        _pinned = ref thing.GetPinnableReference();

        // unsafe cast in IL
        ptr = (byte*)_pinned;
    }
    else
    {
        ptr = default(byte*);
    }

    // <BODY> 
}
finally   // finally can be omitted when not observable
{
    // "unpin" the object
    _pinned = nullptr;
}

BulunmaktadırDrawbacks

  • GetPinnableReference yalnızca içinde kullanılmak üzere tasarlanmıştır fixed , ancak güvenli kodda kullanımını hiçbir şey engellemez, bu yüzden uygulayıcıyı göz önünde bulundurmanız gerekir.GetPinnableReference is intended to be used only in fixed, but nothing prevents its use in safe code, so implementor must keep that in mind.

AlternatiflerAlternatives

Kullanıcılar GetPinnableReference veya benzeri bir üyeyi ortaya çıkarabilir ve bunu şu şekilde kullanabilirUsers can introduce GetPinnableReference or similar member and use it as

fixed(byte* ptr = thing.GetPinnableReference())
{ 
    // <BODY>
}

Alternatif çözüm isteniyorsa, için çözüm yoktur System.String .There is no solution for System.String if alternative solution is desired.

Çözümlenmemiş sorularUnresolved questions

  • [] "Boş" durumundaki davranış.[ ] Behavior in "empty" state. - nullptr or undefined ? - nullptr or undefined ?
  • [] Uzantı yöntemleri göz önünde bulundurulmalıdır mi?[ ] Should the extension methods be considered ?
  • [] Üzerinde bir model algılanırsa System.String , bunun yerine mi kazanamalıdır?[ ] If a pattern is detected on System.String, should it win over ?

Tasarım toplantılarıDesign meetings

Henüz yok.None yet.