InteroperabilityEdit
Omdat computersystemen vaak interactie vereisen tussen nieuwere en oudere toepassingen, biedt het .NET Framework middelen om toegang te krijgen tot functies die zijn geïmplementeerd in nieuwere en oudere programma’s die buiten de .NET-omgeving worden uitgevoerd. Toegang tot Component Object Model (COM)-componenten wordt verschaft in System.Runtime.InteropServices
en System.EnterpriseServices
namespaces van het framework. Toegang tot andere functies verloopt via Platform Invocation Services (P/Invoke). Toegang tot .NET-functies vanuit native applicaties verloopt via omgekeerde P/Invoke-functie.
TaalonafhankelijkheidEdit
.NET Framework introduceert een Common Type System (CTS) dat alle mogelijke datatypen en programmeerconstructies definieert die door CLR worden ondersteund en hoe ze al dan niet kunnen samenwerken conform de CLI-specificatie. Dankzij deze functie ondersteunt .NET Framework de uitwisseling van typen en objectinstanties tussen bibliotheken en toepassingen die zijn geschreven met elke conforme .NET-taal.
Type safetyEdit
CTS en de CLR die in .NET Framework wordt gebruikt, dwingen ook type safety af. Dit voorkomt slecht gedefinieerde casts, verkeerde methode-aanroepen, en geheugengrootte-problemen bij het benaderen van een object. Dit maakt ook dat de meeste CLI-talen statisch getypeerd zijn (met of zonder type-inferentie). Vanaf .NET Framework 4.0 is de CLR echter uitgebreid met de Dynamic Language Runtime, waardoor dynamisch getypeerde talen boven op de CLI kunnen worden geïmplementeerd.
PortabilityEdit
Hoewel Microsoft nooit het volledige framework op een ander systeem dan Microsoft Windows heeft geïmplementeerd, heeft het het framework cross-platform gemaakt, en zijn er implementaties beschikbaar voor andere besturingssystemen (zie Silverlight en § Alternatieve implementaties). Microsoft heeft de specificaties voor CLI (waaronder de core class libraries, CTS, en CIL), C#, en C++/CLI ingediend bij zowel Ecma International (ECMA) als International Organization for Standardization (ISO), waardoor ze beschikbaar zijn als officiële standaarden. Dit maakt het voor derden mogelijk om compatibele implementaties van het framework en zijn talen op andere platforms te maken.
SecurityEdit
.NET Framework heeft zijn eigen beveiligingsmechanisme met twee algemene kenmerken: Code Access Security (CAS), en validatie en verificatie. CAS is gebaseerd op bewijsmateriaal dat is gekoppeld aan een specifieke assembly. Meestal is het bewijs de bron van de assembly (of deze is geïnstalleerd op de lokale machine of is gedownload van het internet). CAS gebruikt bewijsmateriaal om te bepalen welke rechten aan de code zijn toegekend. Andere code kan eisen dat aanroepende code een gespecificeerde toestemming krijgt. De vraag zorgt ervoor dat CLR een call stack walk uitvoert: elke assembly van elke methode in de call stack wordt gecontroleerd op de vereiste toestemming; als een assembly de toestemming niet krijgt, wordt er een beveiligingsuitzondering gegooid.
Beheerde CIL bytecode is gemakkelijker te reverse-engineeren dan native code, tenzij deze is geobfusceerd. .NET-decompilerprogramma’s stellen ontwikkelaars zonder reverse-engineeringvaardigheden in staat de broncode achter niet-geobfuseerde .NET-assemblies te bekijken. Daarentegen zijn apps die gecompileerd zijn naar native machinecode veel moeilijker te reverse-engineeren, en wordt broncode bijna nooit succesvol geproduceerd, voornamelijk vanwege compileroptimalisaties en gebrek aan reflectie. Dit leidt tot bezorgdheid in het bedrijfsleven over het mogelijke verlies van bedrijfsgeheimen en het omzeilen van licentiecontrolemechanismen. Om dit te beperken, heeft Microsoft sinds 2002 Dotfuscator Community Edition bij Visual Studio .NET geleverd. Verduisteringshulpmiddelen van derden zijn ook verkrijgbaar bij leveranciers als VMware, V.i. Labs, Turbo en Red Gate Software. Methode-level encryptie tools voor .NET code zijn beschikbaar van leveranciers zoals SafeNet.
GeheugenbeheerEdit
CLR bevrijdt de ontwikkelaar van de last van geheugenbeheer (toewijzen en vrijmaken wanneer klaar); het handelt geheugenbeheer zelf af door te detecteren wanneer geheugen veilig kan worden vrijgemaakt. Instantiaties van .NET types (objecten) worden gealloceerd vanuit de beheerde heap; een pool van geheugen beheerd door CLR. Zolang er een verwijzing naar een object bestaat, wat direct kan zijn, of via een grafiek van objecten, wordt het object beschouwd als in gebruik. Wanneer er geen verwijzing naar een object bestaat, en het niet kan worden bereikt of gebruikt, wordt het vuilnis, dat voor ophaling in aanmerking komt.
.NET Framework bevat een garbage collector (GC) die periodiek draait, op een aparte thread van de thread van de applicatie, die alle onbruikbare objecten opsomt en het aan hen toegewezen geheugen terugwint. Het is een niet-deterministische, compacterende, mark-and-sweep vuilnisverzamelaar. GC draait alleen als een bepaalde hoeveelheid geheugen is gebruikt of als er voldoende druk op het systeem is om geheugen te vinden. Aangezien het niet gegarandeerd is wanneer de voorwaarden om geheugen terug te vorderen zijn bereikt, is GC draaien niet-deterministisch. Elke .NET-applicatie heeft een set wortels, dat zijn verwijzingen naar objecten op de beheerde heap (beheerde objecten). Deze omvatten verwijzingen naar statische objecten, objecten gedefinieerd als lokale variabelen of methodeparameters die momenteel in scope zijn, en objecten waarnaar verwezen wordt door CPU-registers. Wanneer GC draait, pauzeert het de applicatie en dan, voor elk object waarnaar verwezen wordt in de root, somt het recursief alle objecten op die bereikbaar zijn vanuit de root objecten en markeert ze als bereikbaar. Het gebruikt CLI metadata en reflectie om de objecten te ontdekken die door een object worden ingekapseld, en loopt ze dan recursief af. Vervolgens worden alle objecten op de heap (die aanvankelijk contigu waren gealloceerd) opgesomd met behulp van reflectie. Alle objecten die niet gemarkeerd zijn als bereikbaar, worden vuilnis. Dit is de markeerfase. Aangezien het geheugen dat door garbage wordt vastgehouden van geen belang is, wordt het beschouwd als vrije ruimte. Er blijft echter ruimte over tussen objecten die aanvankelijk aaneengesloten waren. De objecten worden dan samengeperst om de vrije ruimte op de beheerde heap weer aaneengesloten te maken. Elke verwijzing naar een object dat ongeldig wordt gemaakt door het object te verplaatsen, wordt door GC bijgewerkt om de nieuwe locatie weer te geven. De toepassing wordt hervat na afloop van de garbage collection. De laatste versie van het .NET framework gebruikt gelijktijdige garbage collection samen met gebruikerscode, waardoor pauzes onmerkbaar zijn, omdat ze op de achtergrond worden uitgevoerd.
De garbage collector die door het .NET Framework wordt gebruikt, is ook generationeel. Objecten krijgen een generatie toegewezen. Nieuw aangemaakte objecten krijgen de label Generatie 0. Objecten die één garbage collection overleven, krijgen de label Generatie 1. Generatie 1-objecten die een volgende afvalinzameling overleven, zijn Generatie 2-objecten. Het raamwerk gebruikt tot Generatie 2-objecten. Objecten van een hogere generatie worden minder vaak afgehaald dan objecten van een lagere generatie. Dit verhoogt de efficiëntie van de afvalverzameling, omdat oudere objecten meestal een langere levensduur hebben dan nieuwere objecten. Door oudere objecten in de meeste gevallen te negeren, zijn er in totaal minder controles en verdichtingsoperaties nodig.
PerformanceEdit
Wanneer een applicatie voor het eerst wordt gestart, compileert het .NET Framework de CIL-code in uitvoerbare code met behulp van de just-in-time compiler, en slaat het uitvoerbare programma op in de .NET Native Image Cache. Dankzij caching start de toepassing sneller bij volgende lanceringen, hoewel de eerste lancering meestal trager is. Om de eerste start te versnellen, kunnen ontwikkelaars het hulpprogramma Native Image Generator gebruiken om elke .NET-toepassing handmatig vooraf te compileren en in de cache op te slaan.
De garbage collector, die in de omgeving is geïntegreerd, kan onverwachte vertragingen in de uitvoering veroorzaken waarover de ontwikkelaar weinig directe controle heeft. “In grote toepassingen kan het aantal objecten waarmee de garbage collector moet werken erg groot worden, wat betekent dat het erg lang kan duren om ze allemaal te bezoeken en te herschikken.”
.NET Framework biedt vanaf april 2014 in Visual Studio 2013 Update 2 ondersteuning voor het aanroepen van Streaming SIMD Extensions (SSE) via managed code. Mono biedt echter al ondersteuning voor SIMD Extensions vanaf versie 2.2 binnen de Mono.Simd namespace in 2009. Miguel de Icaza, hoofdontwikkelaar van Mono, heeft de hoop uitgesproken dat deze SIMD-ondersteuning zal worden overgenomen door de ECMA-standaard van CLR. Streaming SIMD Extensions zijn beschikbaar in x86 CPU’s sinds de introductie van de Pentium III. Sommige andere architecturen zoals ARM en MIPS hebben ook SIMD uitbreidingen. Indien de CPU geen ondersteuning heeft voor deze uitbreidingen, worden de instructies in software gesimuleerd.