objective c - Why doesn't a generic NSDictionary warn me about incorrectly-typed key inserts/assignments? -
why don't following nsdictionary/nsmutabledictionary calls produce error or warning?
i expect error here because rhs nsdictionary literal doesn't match generic types of nsdictionary lhs local variable.
nsdictionary<nsstring *, nsnumber *> *foo = @{ @(42) : @"foo" }; i expect error here because key type doesn't match nsmutabledictionary's key generic type:
nsmutabledictionary<nsstring *, nsnumber *> *foo = [nsmutabledictionary new]; // neither of these calls produces error. :( foo[@(42)] = @(42); [foo setobject:@(42) forkey:@(42)]; i see error when try assign improperly-typed value, know generics errors working somewhat:
nsmutabledictionary<nsstring *, nsnumber *> *foo = [nsmutabledictionary new]; foo[@"foo"] = @"bar"; causes following warning:
foo.m:81:16: incompatible pointer types sending 'nsstring *' parameter of type 'nsnumber * _nullable' why don't literal assignment or improperly-typed keys cause warnings/errors?
seems limitation/bug of compiler, caused definition of setobject:forkeyedsubscript: method:
- (void)setobject:(nullable objecttype)obj forkeyedsubscript:(keytype <nscopying>)key; the protocol conforming requirement somehow hides type requirement keytype. if <nscopying> not present, compiler makes keytype check , warns you.
to confirm this, played code, here results:
@interface mydictionary<keytype, objecttype>: nsobject - (void)setobject:(nullable objecttype)obj forkeyedsubscript:(keytype <nscopying>)key; @end ... mydictionary<nsnumber*, nsnumber*>* dict = [[mydictionary alloc] init]; uibutton *button = [[uibutton alloc] initwithframe:cgrectzero]; dict[@"98"] = @14; // no warnings dict[button] = @14; //warning: sending 'uibutton *' parameter of incompatible type 'id<nscopying>' the above code has same behaviour nsmutabledictionary. however, if remove <nscopying> protocol conformance restriction keytype, compiler gives appropriate warning:
@interface mydictionary<keytype, objecttype>: nsobject - (void)setobject:(nullable objecttype)obj forkeyedsubscript:(keytype)key; @end ... mydictionary<nsnumber*, nsnumber*>* dict = [[mydictionary alloc] init]; dict[@"98"] = @14; // warning: incompatible pointer types sending 'nsstring *' parameter of type 'nsnumber *' note. default you'll warnings object types mismatch, if want receive errors, can either enable treat warnings errors build setting, or treat incompatible pointer type warnings errors one.
Comments
Post a Comment