internal
C # 'daki anahtar kelime için pratik kullanımın ne olduğunu açıklar mısınız?
internal
Değiştiricinin mevcut montaja erişimi sınırladığını biliyorum , ancak ne zaman ve hangi durumda kullanmalıyım?
internal
C # 'daki anahtar kelime için pratik kullanımın ne olduğunu açıklar mısınız?
internal
Değiştiricinin mevcut montaja erişimi sınırladığını biliyorum , ancak ne zaman ve hangi durumda kullanmalıyım?
Yanıtlar:
Aynı derlemedeki diğer birçok sınıftan erişmek istediğiniz, ancak diğer derlemelerde kodun erişemediğinden emin olmak istediğiniz yardımcı program veya yardımcı sınıflar / yöntemler.
Gönderen MSDN (archive.org yoluyla):
Dahili erişimin yaygın kullanımı bileşen tabanlı geliştirmedir, çünkü bir grup bileşenin uygulama kodunun geri kalanına maruz kalmadan özel bir şekilde işbirliği yapmasını sağlar. Örneğin, grafiksel kullanıcı arabirimleri oluşturmak için bir çerçeve, iç erişime sahip üyeler kullanarak işbirliği yapan Denetim ve Form sınıfları sağlayabilir. Bu üyeler dahili olduğundan, çerçeveyi kullanan koda maruz kalmazlar.
InternalsVisibleTo
Hedef derleme iç sınıflarına özel erişim izni verilen "arkadaş" derlemeleri oluşturmak için derleme düzeyi özniteliği ile birlikte iç değiştiriciyi de kullanabilirsiniz .
Bu, daha sonra test edilecek düzeneğin dahili üyelerini çağırmasına izin verilen birim test düzeneklerinin oluşturulması için yararlı olabilir. Tabii ki başka montajlara bu erişim seviyesi verilmiyor, bu nedenle sisteminizi serbest bıraktığınızda kapsülleme korunuyor.
Bob'un BigImportantClass'a ihtiyacı varsa, Bob'un A projesine sahip olan kişilere, BigImportantClass'ın ihtiyaçlarını karşılamak için yazılacağını, ihtiyaçlarını karşıladığından emin olmak için test edileceğini, ihtiyaçlarını karşıladığını belgelediğini ve bir sürecin belgelendiğini garanti etmesi gerekir. artık ihtiyaçlarını karşılamayacak şekilde asla değiştirilmemesini sağlamak için uygulanacaktır.
Eğer bir sınıf içsel ise, bu süreçten geçmek zorunda değildir, bu da A Projesi için bütçeyi başka şeylere harcayabilecekleri tasarrufdan kurtarır.
İçsel nokta Bob için hayatı zorlaştırdığı değildir. Proje A'nın özellikler, kullanım ömrü, uyumluluk vb. Hakkında ne pahalı vaatlerde bulunduğunu kontrol etmenizi sağlar.
Internal'i kullanmanın bir başka nedeni, ikili dosyalarınızı gizlemenizdir. Obfuscator, herhangi bir iç sınıfın sınıf adını karıştırmanın güvenli olduğunu bilirken, ortak sınıfların adı karıştırılamaz, çünkü bu mevcut referansları kırabilir.
Basit bir ortak API içine bir ton karmaşık işlevselliği içine alan bir DLL yazıyorsanız, halka açık olarak maruz kalmayacak sınıf üyelerinde "iç" kullanılır.
Karmaşıklığı (diğer bir deyişle kapsülleme) gizlemek, kaliteli yazılım mühendisliğinin ana konseptidir.
Yönetilmeyen kodun üzerine bir sarmalayıcı oluştururken dahili anahtar kelime çok kullanılır.
DllImport yapmak istediğiniz bir C / C ++ tabanlı kitaplığınız varsa, bu işlevleri bir sınıfın statik işlevleri olarak içe aktarabilir ve bunları içsel hale getirebilirsiniz, böylece kullanıcınız orijinal API'ya değil, yalnızca paketinize erişebilir. bir şeyle uğraşmak. Fonksiyonlar statiktir, ihtiyacınız olan çoklu sargı sınıfları için montajın her yerinde kullanabilirsiniz.
Mono.Cairo'ya bir göz atabilirsiniz, bu yaklaşımı kullanan cairo kütüphanesinin etrafındaki bir sarıcıdır.
"Mümkün olduğu kadar katı değiştirici olarak kullan" kuralı tarafından yönetilen, açıkça başka bir derlemeden erişmesi gerekene kadar başka bir sınıftan, başka bir sınıftan metoda erişmem gereken her yerde dahili kullanıyorum.
Montaj arayüzü genellikle sınıf arayüzlerinin toplamından daha dar olduğundan, kullandığım birçok yer var.
Ben iç aşırı aşırı bulmak. belirli işlevsellikleri yalnızca diğer tüketicilere veremeyeceğiniz belirli sınıflara maruz bırakmamalısınız.
Bence bu arayüzü bozuyor, soyutlamayı bozuyor. Bu, asla kullanılmaması gerektiği anlamına gelmez, ancak daha iyi bir çözüm, farklı bir sınıfa yeniden bakmak veya mümkünse farklı bir şekilde kullanmaktır. Ancak, bu her zaman mümkün olmayabilir.
Sorunlara neden olmasının nedenleri, başka bir geliştiricinin sizinkiyle aynı derlemede başka bir sınıf oluşturmakla suçlanabilmesidir. İç kısımlara sahip olmak, soyutlamanın netliğini azaltır ve yanlış kullanıldığında sorunlara neden olabilir. Herkese açık hale getirmiş olmanızla aynı sorun olur. Diğer geliştirici tarafından inşa edilen diğer sınıf, tıpkı herhangi bir dış sınıf gibi, hala bir tüketicidir. Sınıf soyutlama ve kapsülleme sadece dış sınıflar için / sınıflardan koruma için değil, tüm sınıflar için de geçerlidir.
Başka bir sorun, birçok geliştiricinin montajda başka bir yerde kullanmaları gerektiğini düşünecek ve o zaman ihtiyaç duymasalar bile yine de dahili olarak işaretleyecekler. Başka bir geliştirici daha sonra almak için orada olduğunu düşünebilir. Tipik bir ihtiyaç olana kadar özel olarak işaretlemek istersiniz.
Ancak bunların bir kısmı öznel olabilir ve asla kullanılmaması gerektiğini söylemiyorum. Sadece gerektiğinde kullanın.
Geçen gün, belki hafta hatırlayamadığım bir blogda ilginç bir tane gördüm. Temelde bunun için kredi alamıyorum ama yararlı bir uygulama olabilir düşündüm.
Diyelim ki soyut bir sınıfın başka bir meclis tarafından görülmesini istediniz, ama birisinin onu devralmasını istemiyorsunuz. Mühürlü işe yaramaz çünkü bir nedenden dolayı soyuttur, o derlemedeki diğer sınıflar ondan miras alırlar. Özel çalışmaz, çünkü diğer meclisin herhangi bir yerinde bir Ebeveyn sınıfı bildirmek isteyebilirsiniz.
ad alanı Base.Assembly { kamu soyut sınıfı { dahili soyut boşluk SomeMethod (); } // Aynı montajda olduğu için bu iyi çalışıyor. kamu sınıfı ChildWithin: Ebeveyn { iç geçersiz kılma geçersizliği SomeMethod () { } } } namespace Another.Assembly { // Kaboom, çünkü dahili bir yöntemi geçersiz kılamazsınız kamu sınıfı ChildOutside: Ebeveyn { } genel sınıf testi { // Sadece iyi özel Veli _parent; herkese açık Test () { //Hala iyi _parent = yeni ChildWithin (); } } }
Gördüğünüz gibi, birisinin ebeveyn sınıfını miras almadan kullanmasına etkili bir şekilde izin verir.
Bu örnek iki dosya içerir: Assembly1.cs ve Assembly2.cs. İlk dosya dahili bir temel sınıf olan BaseClass'ı içerir. İkinci dosyada, BaseClass'ı örnekleme girişimi bir hata üretir.
// Assembly1.cs
// compile with: /target:library
internal class BaseClass
{
public static int intM = 0;
}
// Assembly1_a.cs
// compile with: /reference:Assembly1.dll
class TestAccess
{
static void Main()
{
BaseClass myBase = new BaseClass(); // CS0122
}
}
Bu örnekte, örnek 1'de kullandığınız dosyaları kullanın ve BaseClass'ın erişilebilirlik düzeyini genel olarak değiştirin . Ayrıca üye IntM'nin erişilebilirlik düzeyini dahili olarak değiştirin . Bu durumda, sınıfı başlatabilirsiniz, ancak dahili üyeye erişemezsiniz.
// Assembly2.cs
// compile with: /target:library
public class BaseClass
{
internal static int intM = 0;
}
// Assembly2_a.cs
// compile with: /reference:Assembly1.dll
public class TestAccess
{
static void Main()
{
BaseClass myBase = new BaseClass(); // Ok.
BaseClass.intM = 444; // CS0117
}
}
kaynak : http://msdn.microsoft.com/tr-tr/library/7c5ka91b(VS.80).aspx
Mevcut derleme kapsamında erişilmesi gereken ve asla dışarıda olmayan yöntemlere, sınıflara vb. Sahip olduğunuzda.
Örneğin, bir DAL'in ORM'si olabilir, ancak nesneler iş katmanına maruz bırakılmamalıdır, tüm etkileşim statik yöntemlerle ve gerekli parametrelerden geçirilerek yapılmalıdır.
Çok ilginç bir iç kullanım - iç üyenin elbette sadece ilan edildiği meclis ile sınırlı olması - bir dereceye kadar "arkadaş" işlevselliği elde etmektir. Bir arkadaş üye, sadece bildirildiği meclis dışındaki diğer meclislerin görebileceği bir şeydir. C # arkadaş için yerleşik bir destek yok, ancak CLR var.
Bir arkadaş montajı bildirmek için InternalsVisibleToAttribute öğesini kullanabilirsiniz ve arkadaş montajından gelen tüm referanslar, arkadaş montajı kapsamında beyan meclisinizin dahili üyelerine herkese açık olarak davranacaktır. Bununla ilgili bir sorun, tüm dahili üyelerin görünür olmasıdır; seçip seçemezsiniz.
InternalsVisibleTo için iyi bir kullanım, çeşitli dahili üyeleri bir birim test düzeneğine maruz bırakmak ve böylece bu üyeleri test etmek için etraftaki karmaşık yansıma çalışmalarına olan ihtiyacı ortadan kaldırmaktır. Tüm iç üyelerin görünür olması pek bir sorun oluşturmaz, ancak bu yaklaşımı kullanmak sınıf arayüzlerinizi oldukça ağır bir şekilde emer ve ilan eden meclis içindeki kapsüllenmeyi mahvedebilir.
Genel kural olarak iki tür üye vardır:
Gürültü azaltma, ne kadar az poz verirseniz kitaplığınız o kadar basit olur. Sabotaj prova / Güvenlik başka bir şeydir (Yansıma buna karşı kazansa da).
Dahili sınıflar, derlemenizin API'sını sınırlamanızı sağlar. Bunun, API'nızın anlaşılmasını kolaylaştırmak gibi avantajları vardır.
Ayrıca, montajınızda bir hata varsa, düzeltmenin kırılma değişikliği getirme şansı daha azdır. İç sınıflar olmadan, herhangi bir sınıfın kamu üyelerini değiştirmenin kırıcı bir değişiklik olacağını varsaymanız gerekir. İç sınıflarda, genel üyelerini değiştirmenin yalnızca derlemenin (ve InternalsVisibleTo özniteliğinde başvurulan tüm derlemeler) iç API'sini bozduğunu varsayabilirsiniz.
Sınıf düzeyinde ve montaj düzeyinde kapsülleme yapmayı seviyorum. Buna katılmayanlar var, ancak işlevselliğin mevcut olduğunu bilmek güzel.
Veri arka uç için LINQ-SQL kullanan bir proje var. İki ana ad alanım var: Biz ve Data. LINQ veri modeli Veri'de yaşar ve "dahili" olarak işaretlenir; Biz ad alanında LINQ veri sınıflarının etrafını saran ortak sınıflar bulunur.
Yani var Data.Client
ve Biz.Client
; ikincisi veri nesnesinin ilgili tüm özelliklerini ortaya koyar, örneğin:
private Data.Client _client;
public int Id { get { return _client.Id; } set { _client.Id = value; } }
Biz nesnelerinin özel bir kurucusu (fabrika yöntemlerinin kullanımını zorlamak için) ve şöyle görünen bir iç kurucusu vardır:
internal Client(Data.Client client) {
this._client = client;
}
Bu, kütüphanedeki işletme sınıflarından herhangi biri tarafından kullanılabilir, ancak ön uç (UI) veri modeline doğrudan erişmenin bir yolu yoktur, bu da iş katmanının her zaman bir aracı görevi görmesini sağlar.
İlk defa internal
çok fazla kullandım ve oldukça kullanışlı olduğunu kanıtladım.
Sınıfların üyelerini oluşturmanın mantıklı olduğu durumlar vardır internal
. Bir örnek, sınıfların nasıl somutlaştırıldığını kontrol etmek istiyorsanız; diyelim ki sınıf örnekleri oluşturmak için bir çeşit fabrika sağlıyorsunuz. Oluşturucuyu yapabilirsiniz internal
, böylece fabrika (aynı derlemede bulunan) sınıfın örneklerini oluşturabilir, ancak bu derlemenin dışındaki kodlar oluşturulamaz.
Ancak, ben sınıfları veya üye yapma herhangi bir noktayı göremiyorum internal
bunları yapmak mantıklı olarak Sadece küçük gibi özel nedenlerle olmadan public
veya private
belirli bir sebep olmaksızın.
dahili anahtar kelimeyi hiç kullandığım tek şey ürünümdeki lisans kontrol kodudur ;-)
Dahili anahtar kelimenin bir kullanımı, derlemenizin kullanıcısının somut uygulamalarına erişimi sınırlamaktır.
Nesneleri oluşturmak için bir fabrikanız veya başka bir merkezi konumunuz varsa, montajınızın kullanıcısı yalnızca genel arabirim veya soyut temel sınıfla ilgilenmelidir.
Ayrıca, iç yapıcılar, başka bir genel sınıfın nerede ve ne zaman başlatıldığını denetlemenize izin verir.
Buna ne dersiniz: Genellikle bir List nesnesini bir montajın harici kullanıcılarına göstermemeniz, bunun yerine bir IEnumerable'ı göstermeniz önerilir. Ancak dizi sözdizimini ve diğer tüm Liste yöntemlerini aldığınız için, derlemenin içinde bir List nesnesi kullanmak çok daha kolaydır. Yani, genellikle derleme içinde kullanılacak bir liste ortaya bir iç özellik var.
Bu yaklaşım hakkında yorumlarınızı bekliyoruz.
public
Birisi proje ad alanınıza baktığında, olarak tanımlanan herhangi bir sınıfın otomatik olarak zekâda görüneceğini unutmayın. API perspektifinden bakıldığında, projenizin kullanıcılarına yalnızca kullanabilecekleri sınıfları göstermek önemlidir. internal
Görmemesi gereken şeyleri gizlemek için anahtar kelimeyi kullanın .
Eğer senin Big_Important_Class
Proje A projeniz dışında kullanılmak üzere tasarlanmıştır, o zaman işaretlemek olmamalıdır internal
.
Ancak, birçok projede, genellikle sadece bir proje içinde kullanılmak üzere tasarlanmış sınıflara sahip olursunuz. Örneğin, parametreli bir iş parçacığı çağırma argümanlarını tutan bir sınıfınız olabilir. Bu durumlarda, internal
kendinizi yolda istenmeyen bir API değişikliğinden korumaktan başka bir sebep yokmuş gibi işaretlemelisiniz .
private
Anahtar kelime yalnızca başka sınıf veya yapı içinde tanımlanan sınıfları veya yapılar üzerinde de kullanılabilir. Bir ad alanı içinde tanımlanan bir sınıf yalnızca public
veya olarak bildirilebilir internal
.
Buradaki fikir, bir kütüphane tasarlarken yalnızca dışarıdan (kütüphanenizin müşterileri tarafından) kullanılması amaçlanan sınıfların herkese açık olması gerektiğidir. Bu şekilde
vb.
İç unsurları kullanmaktan ziyade şirket içi çözümler geliştiriyorsanız, o kadar önemli değil sanırım, çünkü genellikle müşteriler sizinle sürekli iletişim kuracak ve / veya koda erişebilecektir. Yine de kütüphane geliştiricileri için oldukça kritiktirler.
Nesneye Dayalı Paradigma tam olarak uymayan, tehlikeli şeyler yapan, kontrolünüz altındaki diğer sınıflardan ve yöntemlerden çağrılması gereken ve başkalarının kullanmasına izin vermek istemediğiniz sınıflarınız veya yöntemleriniz olduğunda .
public class DangerousClass {
public void SafeMethod() { }
internal void UpdateGlobalStateInSomeBizarreWay() { }
}