2014-07-26 2 views
1

Pourquoi l'extension Array suivante se bloque si le tableau utilisé avec elle est de type UInt, mais fonctionne si le tableau est de type Int ou String?Fusion rapide en tant que plantage générique avec UInt

extension Array 
{ 
func indexOf<T:Equatable>(value:T) -> Int? 
{ 
    for (i, val) in enumerate(self) 
    { 
     if (val as T == value) 
     { 
      return i; 
     } 
    } 
    return nil; 
} 
} 

var a:[UInt] = [243, 234, 1, 212, 3, 56, 88, 11, 77]; 
var i = a.indexOf(234); 

erreur produite:

exécution aire de jeu a échoué: erreur: l'exécution a été interrompue, motif: EXC_BREAKPOINT (code = EXC_I386_BPT, subcode = 0x0). Le processus a été laissé à l'endroit où il a été interrompu, utilisez "thread return -x" pour revenir à l'état avant l'évaluation de l'expression. * fil # 1: tid = 0x27a3c, 0x00000001079d3f27 libswift_stdlib_core.dylib swift_dynamicCast + 1063, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0) * frame #0: 0x00000001079d3f27 libswift_stdlib_core.dylib swift_dynamicCast + 1063 cadre # 1: 0x00000001137bbbc8

+0

Où est la différence avec votre question précédente (maintenant supprimée) http://stackoverflow.com/questions/24971573/extending-swift-array-with-indexof-crashes-with-uint-typed-array? –

+0

Où est la pertinence de votre commentaire par rapport à votre commentaire dans ma question précédente ?! – BadmintonCat

+0

duplication possible de [Array extension pour supprimer l'objet par valeur] (http://stackoverflow.com/questions/24938948/array-extension-to-remove-object-by-value) –

Répondre

1

Le problème est que la T: Equatable que vous définissez est sans rapport avec la T qui est stocké dans le tableau. Lorsque vous effectuez val as T, vous convertissez à partir du type de valeur de tableau à votre nouveau T local qui doit être équivalent.

Lorsque vous appelez indexOf avec un littéral, il n'est pas forcé dans le même type que celui qui est stocké dans a car le type n'est pas appliqué pour correspondre à votre extension.

Vous êtes mieux avec une fonction pour obtenir l'index d'un objet dans un tableau:

func indexOfObject<T : Equatable>(object: T, inArray collection: [T]) -> Int? { 
    var index : Int = 0 
    for testObject in collection { 
     if testObject == object { 
      return index 
     } 
     index++ 
    } 
    return nil 
} 

qui applique strictement que le type T est assimilables et correspond au type de l'objet transmis.

Mieux encore, vous pouvez utiliser une extension comme ceci:

extension Array { 
    func indexOfObjectPassingTest(test: (object: T) -> Bool) -> Int? { 
     var index : Int = 0 
     for object in self { 
      if test(object: object) { 
       return index 
      } 
      index++ 
     } 
     return nil 
    } 
} 

Que je s plus souple et vous permet de le faire:

var i = a.indexOfObjectPassingTest({$0 == 234}) 

Notez également que je ne définit pas T pour ma méthode, car elle est déjà définie dans le tableau lui-même.

+0

Merci pour l'explication rapide et l'exemple! Semble une extension ne sera pas adapté pour cela. – BadmintonCat

+0

Peut-être que je ne vois pas encore la flexibilité mais je crois que les fermetures ne devraient pas être nécessaires pour un simple appel indexOf. – BadmintonCat

+0

@Avalon, une fermeture est seulement "nécessaire" dans ce cas car vous ne pouvez pas garantir que tous les types stockés dans un tableau sont équitables. Cela vous donne la flexibilité supplémentaire de faire des types infinis de tests pour trouver un objet, le tout avec une méthode. Par exemple, vous pouvez utiliser '{$ 0> 234}' pour trouver le premier index supérieur à 234. Vous pouvez également utiliser '{$ 0 === someObj}' pour un tableau qui stocke un type de référence (un type Class) – drewag

Questions connexes