it-swarm.dev

Was ist typsicher?

Was bedeutet "typsicher"?

210
Razin

Typensicherheit bedeutet, dass der Compiler beim Kompilieren Typen validiert und einen Fehler ausgibt, wenn Sie versuchen, einer Variablen den falschen Typ zuzuweisen.

Einige einfache Beispiele:

// Fails, Trying to put an integer in a string
String one = 1;
// Also fails.
int foo = "bar";

Dies gilt auch für Methodenargumente, da Sie explizite Typen an sie übergeben:

int AddTwoNumbers(int a, int b)
{
    return a + b;
}

Wenn ich versucht habe, das anzurufen mit:

int Sum = AddTwoNumbers(5, "5");

Der Compiler gibt einen Fehler aus, da ich eine Zeichenfolge ("5") übergeben habe und eine Ganzzahl erwartet wird.

In einer locker getippten Sprache, wie z. B. Javascript, kann ich Folgendes tun:

function AddTwoNumbers(a, b)
{
    return a + b;
}

wenn ich es so nenne:

Sum = AddTwoNumbers(5, "5");

Javascript konvertiert die 5 automatisch in eine Zeichenfolge und gibt "55" zurück. Dies ist auf Javascript zurückzuführen, das das Zeichen + für die Verkettung von Zeichenfolgen verwendet. Um es typabhängig zu machen, müssten Sie Folgendes tun:

function AddTwoNumbers(a, b)
{
    return Number(a) + Number(b);
}

Oder möglicherweise:

function AddOnlyTwoNumbers(a, b)
{
    if (isNaN(a) || isNaN(b))
        return false;
    return Number(a) + Number(b);
}

wenn ich es so nenne:

Sum = AddTwoNumbers(5, " dogs");

Javascript konvertiert die 5 automatisch in eine Zeichenfolge und fügt sie hinzu, um "5 Hunde" zurückzugeben.

Nicht alle dynamischen Sprachen sind so verzeihend wie Javascript (tatsächlich impliziert eine dynamische Sprache keine lockere typisierte Sprache (siehe Python)), einige von ihnen geben Ihnen tatsächlich einen Laufzeitfehler bei der ungültigen Typumwandlung.

Es ist zwar praktisch, öffnet jedoch eine Reihe von Fehlern, die leicht übersehen werden können und nur durch Testen des laufenden Programms identifiziert werden können. Ich persönlich bevorzuge es mir, wenn mein Compiler mir sagt, ob ich diesen Fehler gemacht habe.

Nun zurück zu C # ...

C # unterstützt ein Sprachfeature namens covariance . Dies bedeutet im Wesentlichen, dass Sie einen Basistyp durch einen untergeordneten Typ ersetzen können und keinen Fehler verursachen können. Beispiel:

 public class Foo : Bar
 {
 }

Hier habe ich eine neue Klasse (Foo) erstellt, die Bar unterordnet. Ich kann jetzt eine Methode erstellen:

 void DoSomething(Bar myBar)

Rufen Sie es mit einem Foo oder einem Bar als Argument auf. Beide funktionieren ohne Fehler. Dies funktioniert, weil C # weiß, dass jede untergeordnete Klasse von Bar die Benutzeroberfläche von Bar implementiert.

Sie können jedoch nicht die Umkehrung ausführen:

void DoSomething(Foo myFoo)

In dieser Situation kann ich Bar nicht an diese Methode übergeben, da der Compiler nicht weiß, dass Bar die Schnittstelle von Foo implementiert. Dies liegt daran, dass eine untergeordnete Klasse sich sehr von der übergeordneten Klasse unterscheiden kann (und dies in der Regel auch wird).

Natürlich bin ich jetzt vom tiefen Ende und über den Rahmen der ursprünglichen Frage hinausgegangen, aber es ist alles gute Sachen zu wissen :)

215
FlySwat

Typsicherheit sollte nicht mit statischer/dynamischer Typisierung oder starker/schwacher Typisierung verwechselt werden.

Eine typsichere Sprache ist eine Sprache, in der die einzigen Vorgänge, die mit Daten ausgeführt werden können, diejenigen sind, die vom Datentyp geduldet werden. Das heißt, wenn Ihre Daten vom Typ X sind und X die Operation y nicht unterstützt, können Sie y(X) nicht in der Sprache ausführen.

Diese Definition legt keine Regeln für fest, wenn diese Option aktiviert ist. Dies kann zur Kompilierzeit (statische Typisierung) oder zur Laufzeit (dynamische Typisierung) erfolgen, normalerweise durch Ausnahmen. Es kann beides sein: In einigen statisch typisierten Sprachen können Sie Daten von einem Typ in einen anderen umwandeln, und die Gültigkeit von Umsetzungen muss zur Laufzeit geprüft werden (stellen Sie sich vor, Sie versuchen, eine Object in eine Consumer - den Compiler umzuwandeln kann nicht wissen, ob es akzeptabel ist oder nicht).

Typensicherheit bedeutet auch nicht unbedingt stark typisiert - manche Sprachen sind notorisch schwach typisiert, aber dennoch typsicher. Nehmen Sie zum Beispiel Javascript: Sein Typensystem ist so schwach wie es kommt, aber immer noch streng definiert. Es ermöglicht das automatische Umwandeln von Daten (z. B. Zeichenfolgen in Ints), jedoch innerhalb klar definierter Regeln. Meines Wissens gibt es keinen Fall, in dem sich ein Javascript-Programm undefiniert verhält, und wenn Sie klug genug sind (ich nicht), sollten Sie vorhersagen können, was beim Lesen von Javascript-Code passieren wird.

Ein Beispiel für eine typsichere Programmiersprache ist C: Das Lesen/Schreiben eines Array-Werts außerhalb der Array-Grenzen hat ein undefiniertes Verhalten nach Spezifikation. Es ist unmöglich vorherzusagen, was passieren wird. C ist eine Sprache, die ein Typsystem hat, aber nicht typsicher ist.

41
Nicolas Rinaudo

Viele Antworten hier kombinieren die Typsicherheit mit statischer Typisierung und dynamischer Typisierung. Eine dynamisch typisierte Sprache (wie Smalltalk) kann auch typsicher sein.

Eine kurze Antwort: Eine Sprache gilt als typsicher, wenn keine Operation zu undefiniertem Verhalten führt. Viele halten das Erfordernis expliziter Typkonvertierungen für erforderlich, damit eine Sprache streng typisiert werden kann, da automatische Konvertierungen manchmal zu genau definierten, aber unerwarteten/nicht intuitiven Verhaltensweisen führen können.

26
ididak

Typensicherheit ist nicht nur eine Kompilierzeitbeschränkung, sondern eine Laufzeit Einschränkung. Ich habe das Gefühl, dass wir auch nach all dieser Zeit noch Klarheit schaffen können. 

Es gibt zwei Hauptprobleme im Zusammenhang mit der Typsicherheit. Speicher ** und Datentyp (mit den entsprechenden Operationen).

Erinnerung**

Eine char erfordert normalerweise 1 Byte pro Zeichen oder 8 Bits (abhängig von der Sprache, Java und C # speichern Unicode-Zeichen, die 16 Bit erfordern) . Eine int erfordert 4 Byte oder 32 Bit (normalerweise).

Visuell:

char: |-|-|-|-|-|-|-|-|

int : |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

Eine typsichere Sprache erlaubt nicht, dass ein int zur Laufzeit run-time in ein Zeichen eingefügt wird (dies sollte eine Art Klassenumwandlung oder eine Ausnahme aus dem Speicher auslösen). In einer vom Typ unsicheren Sprache würden Sie jedoch vorhandene Daten in 3 weiteren Bytes neben dem Arbeitsspeicher überschreiben.

int >> char:

|-|-|-|-|-|-|-|-| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?|

In dem obigen Fall werden die 3 Bytes auf der rechten Seite überschrieben, sodass alle Zeiger auf diesen Speicher (z. B. 3 aufeinanderfolgende Zeichen), die einen vorhersagbaren Zeichenwert erwarten, jetzt überflüssig sind. Dies führt zu undefined-Verhalten in Ihrem Programm (oder, was noch schlimmer ist, möglicherweise in anderen Programmen, je nachdem, wie das Betriebssystem Speicher belegt - sehr unwahrscheinlich heutzutage). 

** Während sich das erste Problem technisch nicht mit dem Datentyp befasst, geben Sie sichere Sprachen inhärent an und beschreiben das Problem visuell für diejenigen, die nicht wissen, wie die Speicherzuordnung "aussieht".

Datentyp

Das subtilere und direktere Typproblem besteht darin, dass zwei Datentypen dieselbe Speicherzuordnung verwenden. Nimm ein int vs ein vorzeichenloses int. Beide sind 32 Bit. (Genauso leicht könnten ein Zeichen [4] und ein int sein, aber das häufigste Problem ist uint vs. int).

|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

Ein Typ unsicherer Sprache ermöglicht es dem Programmierer, auf einen ordnungsgemäß zugewiesenen Bereich von 32 Bit zu verweisen, aber wenn der Wert eines vorzeichenlosen int in den Raum eines int (oder umgekehrt) gelesen wird, haben wir wieder undefined. Stellen Sie sich vor, welche Probleme dies bei einem Bankprogramm verursachen kann: 

"Dude! Ich habe $ 30 überzogen und jetzt sind noch $ 65.506 übrig !!"

Natürlich verwenden Bankprogramme viel größere Datentypen. ;) LOL!

Wie schon andere darauf hingewiesen haben, geht es als nächstes um Rechenoperationen für Typen. Das ist bereits ausreichend abgedeckt.

Geschwindigkeit gegen Sicherheit

Die meisten Programmierer müssen sich heutzutage nie um solche Dinge kümmern, es sei denn, sie verwenden etwas wie C oder C++. In beiden Sprachen kann der Programmierer die Typensicherheit zur Laufzeit (direkte Speicherreferenzierung) leicht verletzen, obwohl die Compiler bestrebt sind, das Risiko zu minimieren. Dies ist jedoch nicht alles schlecht. 

Ein Grund dafür, dass diese Sprachen so schnell sind, dass sie nicht durch die Überprüfung der Typkompatibilität während Laufzeitoperationen wie beispielsweise Java belastet werden. Sie gehen davon aus, dass der Entwickler ein vernünftiges rationales Wesen ist, das keine Zeichenkette und kein Intellekt zusammenfügt. Dafür wird der Entwickler mit Geschwindigkeit und Effizienz belohnt.

17
Gr3go

Eine Erklärung aus einem Liberal Arts Major, nicht einem Comp Sci Major:

Wenn Leute sagen, dass eine Sprache oder ein Sprachmerkmal typsicher ist, bedeutet dies, dass die Sprache Sie beispielsweise daran hindern wird, etwas zu übergeben, das keine Ganzzahl ist, an eine Logik, die eine Ganzzahl erwartet.

In C # definiere ich zum Beispiel eine Funktion als:

 void foo(int arg)

Der Compiler wird mich dann davon abhalten: 

  // call foo
  foo("hello world")

In anderen Sprachen würde der Compiler mich nicht aufhalten (oder es gibt keinen Compiler ...), so dass der String an die Logik übergeben wird und dann wahrscheinlich etwas Schlimmes passiert.

Geben Sie sichere Sprachen ein, um mehr zur "Kompilierzeit" zu fangen.

Auf der anderen Seite, mit typsicheren Sprachen, wenn Sie einen String wie "123" haben und ihn wie ein int bearbeiten wollen, müssen Sie mehr Code schreiben, um den String in einen int zu konvertieren, oder wenn Sie einen int haben wie 123 und möchten es in einer Nachricht wie "Die Antwort ist 123" verwenden, müssen Sie mehr Code schreiben, um es in eine Zeichenfolge umzuwandeln.

8
Corey Trager

Eine Programmiersprache, die 'typsicher' ist, bedeutet Folgendes:

  1. Sie können nicht von nicht initialisierten Variablen lesen
  2. Sie können Arrays nicht über ihre Grenzen hinaus indizieren
  3. Sie können keine ungeprüften Typumwandlungen durchführen
8
Kekule

Um ein besseres Verständnis zu erhalten, schauen Sie sich das folgende Video an, das Code in typsicherer Sprache (C #) und NICHT typsicherer Sprache (Javascript) veranschaulicht.

http://www.youtube.com/watch?v=Rlw_njQhkxw

Nun zum langen Text.

Typensicherheit bedeutet, Typfehler zu vermeiden. Ein Typfehler tritt auf, wenn der Datentyp eines Typs einem anderen Typ UNKNOWINGLY zugewiesen wird und unerwünschte Ergebnisse erzielt werden.

Zum Beispiel ist JavaScript NICHT eine typsichere Sprache. Im folgenden Code ist "num" eine numerische Variable und "str" ​​ist ein String. Javascript erlaubt es mir, "num + str" zu tun, jetzt wird GUESS das Rechnen oder Verketten durchführen.

Für den folgenden Code sind die Ergebnisse "55", aber der wichtige Punkt ist die Verwirrung, die durch die Art der Operation hervorgerufen wird. 

Dies geschieht, weil Javascript keine typsichere Sprache ist. Dadurch kann ein Datentyp ohne Einschränkungen auf den anderen Datentyp gesetzt werden.

<script>
var num = 5; // numeric
var str = "5"; // string
var z = num + str; // arthimetic or concat ????
alert(z); // displays  “55”
</script>

C # ist eine typsichere Sprache. Es erlaubt nicht, dass ein Datentyp einem anderen Datentyp zugewiesen wird. Der nachstehende Code erlaubt keinen "+" - Operator für verschiedene Datentypen.

enter image description here

4

Typsicher bedeutet, dass der Datentyp für eine Variable, einen Rückgabewert oder ein Argument programmgesteuert in ein bestimmtes Kriterium passen muss.

In der Praxis bedeutet dies, dass sich 7 (ein ganzzahliger Typ) von "7" (ein Anführungszeichen des Stringtyps) unterscheidet.

PHP, Javascript und andere dynamische Skriptsprachen sind normalerweise schwach typisiert. Sie konvertieren eine (Zeichenfolge) "7" in eine (Ganzzahl) 7, wenn Sie versuchen, "7" + 3 hinzuzufügen explizit (und Javascript verwendet das "+" - Zeichen für die Verkettung).

C/C++/Java wird das nicht verstehen oder das Ergebnis in "73" verketten. Durch Typensicherheit werden diese Arten von Fehlern im Code verhindert, indem die Typanforderung explizit gemacht wird.

Typensicherheit ist sehr nützlich. Die Lösung für die obige "7" + 3 wäre die Eingabe von cast (int) "7" + 3 (entspricht 10).

4
Jared Farrish

Versuchen Sie diese Erklärung bei ...

TypeSafe bedeutet, dass Variablen zur Kompilierzeit statisch auf geeignete Zuordnung überprüft werden. Verwenden Sie beispielsweise eine Zeichenfolge oder eine Ganzzahl. Diese zwei unterschiedlichen Datentypen können nicht über Kreuz zugewiesen werden (dh Sie können einer Zeichenfolge weder eine Ganzzahl noch einer Ganzzahl eine Zeichenfolge zuweisen).

Beachten Sie Folgendes für nicht typsicheres Verhalten:

object x = 89;
int y;

wenn Sie versuchen, dies zu tun:

y = x;

der Compiler gibt einen Fehler aus, der besagt, dass ein System.Object nicht in eine Ganzzahl konvertiert werden kann. Sie müssen das explizit tun. Ein Weg wäre:

y = Convert.ToInt32( x );

Die obige Zuordnung ist nicht typensicher. Bei einer typsicheren Zuordnung können die Typen direkt einander zugeordnet werden. 

In ASP.NET gibt es nicht typensichere Sammlungen (z. B. die Anwendungs-, Sitzungs- und Viewstate-Sammlungen). Die gute Nachricht über diese Sammlungen ist, dass Sie (bei der Minimierung der Verwaltung mehrerer Serverzustände) nahezu jeden Datentyp in jede der drei Sammlungen einfügen können. Die schlechte Nachricht: Da diese Sammlungen nicht typsicher sind, müssen Sie die Werte entsprechend umwandeln, wenn Sie sie wieder abrufen. 

Zum Beispiel:

Session[ "x" ] = 34;

funktioniert gut. Um den Integer-Wert wieder zuzuweisen, müssen Sie jedoch Folgendes tun:

int i = Convert.ToInt32( Session[ "x" ] );

Informieren Sie sich über Generika, wie Sie mithilfe von Facility typsichere Sammlungen problemlos implementieren können. 

C # ist eine typsichere Sprache, aber achten Sie auf Artikel zu C # 4.0. interessante dynamische Möglichkeiten stehen im Vordergrund (ist es eine gute Sache, dass C # im Wesentlichen Option Strict erhält: Aus ... wir werden sehen).

2
rp.

Type-Safe ist ein Code, der nur auf die Speicherorte zugreift, auf die er zugreifen darf, und nur auf genau definierte, zulässige Weise. Typsicherer Code kann keine Operation für ein Objekt ausführen, das für dieses Objekt ungültig ist. Die Compiler für die Sprachen C # und VB.NET produzieren immer typsicheren Code, der während der JIT-Kompilierung als typsicher gilt.

2
Jonuz

Typsicher bedeutet, dass die Menge von Werten, die einer Programmvariablen zugewiesen werden können, genau definierten und überprüfbaren Kriterien entsprechen muss. Typensichere Variablen führen zu robusteren Programmen, da die Algorithmen, die die Variablen bearbeiten, darauf vertrauen können, dass die Variable nur einen bestimmten Wertebereich enthält. Dieses Vertrauen zu erhalten, sichert die Integrität und Qualität der Daten und des Programms. 

Bei vielen Variablen wird der Satz von Werten, die einer Variablen zugewiesen werden können, zu dem Zeitpunkt definiert, zu dem das Programm geschrieben wird. Beispielsweise kann eine Variable mit dem Namen "color" die Werte "rot", "grün" oder "blau" annehmen und niemals andere Werte. Bei anderen Variablen können sich diese Kriterien zur Laufzeit ändern. Beispielsweise darf eine Variable mit dem Namen "color" nur Werte in der Spalte "name" einer Tabelle "Colors" in einer relationalen Datenbank annehmen, wobei "rot", "grün" und "blau" drei Werte sind für "Name" in der Tabelle "Farben", aber ein anderer Teil des Computerprogramms kann dieser Liste möglicherweise hinzugefügt werden, während das Programm ausgeführt wird, und die Variable kann die neuen Werte annehmen, nachdem sie der Tabelle "Farben" hinzugefügt wurden . 

Viele typsichere Sprachen machen die Illusion von "Typsicherheit", indem sie darauf bestehen, Typen für Variablen streng zu definieren und nur zulassen, dass einer Variablen Werte des gleichen "Typs" zugewiesen werden. Bei diesem Ansatz gibt es einige Probleme. Ein Programm kann beispielsweise eine Variable "yearOfBirth" haben, in dem das Jahr geboren wurde, in dem die Person geboren wurde, und es ist verlockend, sie als kurze Ganzzahl zu typisieren. Es ist jedoch keine kurze ganze Zahl. In diesem Jahr ist es eine Zahl, die unter 2009 und über -10000 liegt. Dieses Set wächst jedoch jedes Jahr um 1, wenn das Programm ausgeführt wird. Dies als "short int" zu definieren ist nicht ausreichend. Um diese Variable typsicher zu machen, wird eine Laufzeitvalidierungsfunktion benötigt, die sicherstellt, dass die Anzahl immer größer als -10000 ist und unter dem nächsten Kalenderjahr liegt. Es gibt keinen Compiler, der solche Kriterien durchsetzen kann, da diese Kriterien immer eindeutige Merkmale der Problemdomäne sind. 

Sprachen, die dynamische Typisierung verwenden (oder Duck-Typing oder Manifest-Typisierung), wie Perl, Python, Ruby, SQLite und Lua, haben keine typisierten Variablen. Dadurch wird der Programmierer gezwungen, für jede Variable eine Laufzeitvalidierungsroutine zu schreiben, um sicherzustellen, dass sie korrekt ist, oder die Folgen unerklärlicher Laufzeitausnahmen zu ertragen. Nach meiner Erfahrung denken Programmierer in statisch typisierten Sprachen wie C, C++, Java und C # oft daran, dass nur statisch definierte Typen erforderlich sind, um die Vorteile der Typsicherheit zu nutzen. Dies trifft für viele nützliche Computerprogramme einfach nicht zu, und es ist schwer vorherzusagen, ob dies für ein bestimmtes Computerprogramm zutrifft. 

Das lange und das kurze .... Wollen Sie die Sicherheit der Typen? Wenn dies der Fall ist, schreiben Sie Laufzeitfunktionen, um sicherzustellen, dass eine Variable einen zugewiesenen Wert erfüllt und genau definierten Kriterien entspricht. Der Nachteil ist, dass die Domänenanalyse für die meisten Computerprogramme wirklich schwierig ist, da Sie die Kriterien für jede Programmvariable explizit definieren müssen. 

1
Jay Godse

Konzept:

Um ganz einfach zu sein. Typsicher wie die Bedeutungen, stellt sicher, dass der Typ der Variablen sicher sein sollte 

  1. kein falscher Datentyp, z. Eine Variable vom String-Typ kann nicht mit Ganzzahl gespeichert oder initialisiert werden
  2. Auf gebundene Indizes kann nicht zugegriffen werden
  3. Erlaube nur den spezifischen Speicherplatz 

es geht also um die Sicherheit der Speicherarten in Bezug auf Variablen. 

0
azizsagi