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