Objective-C 程序设计语言采用特定的语法,来定义类和方法、调用对象的方法、动态地扩展类,以及创建编程接口,来解决具体问题。Objective-C 作为 C 程序设计语言的超集,支持与 C 相同的基本语法。有C#语言的编程经验,那么Objective-C将更容易上手,本文将从各个方面对比C#与Objective-C的语法。
class="brush: csharp; auto-links: true; collapse: false; first-line: 1; gutter: true; html-script: true; light: false; ruler: false; smart-tabs: true; tab-size: 2; toolbar: true;">C#: string name = “lwme.cnblogs.com”; Objective-C: NSString *name = @”lwme.cnblogs.com”;
字符串前面的@符号是objc在标准C语言基础上添加的特性,"SteveZ"前面有一个@符号表示字符串应该作为Cocoa的NSString来处理,是把C string转换成NSString的一个简写。
C#: name.Length Objective-C: [name length] name.length
C#: int i = 10; string age = i.ToString(); int intAge = int.Parse(age); Objective-C: NSInteger i = 10; NSString *age = [@(i) stringValue]; // 转换成NSNumber再获取字符串值 NSString *age = [NSString stringWithFormat:@"%d", i]; NSInteger intAge = [age integerValue];
C#: string host = "lwme" + ".cnblogs.com"; Objective-C: NSString *host = @"lwme" @".cnblogs.com" NSString *host = [@"lwme" stringByAppendingString:@".cnblogs.com"]; NSString *host = [NSString stringWithFormat:@"%@%@", @"lwme", @".cnblogs.com"];
C#: bool isEqual = strA == strB; bool isEqual = string.Compare(strA, strB, true) == 0; // 忽略大小写 bool isEqual = string.Compare(strA, strB, StringComparison.InvariantCultureIgnoreCase) == 0; bool isStartWith = strA.StartsWith(strB); bool isStartWith = strA.StartsWith(strB, StringComparison.InvariantCultureIgnoreCase); bool isEndWith = strA.EndsWith(strB); bool isEndWith = strA.EndsWith(strB, StringComparison.InvariantCultureIgnoreCase); bool isContain = strA.Contains(strB); bool isContain = strA.Contains(strB, StringComparison.InvariantCultureIgnoreCase); Objective-C: BOOL isEqual = [strA isEqualToString: strB]; BOOL isEqual = [strA caseInsensitiveCompare:strB] == NSOrderedSame; // 忽略大小写 BOOL isEqual = [strA compare:strB options:NSCaseInsensitiveSearch] == NSOrderedSame; BOOL isStartWith = [strA hasPrefix:strB]; BOOL isEndWith = [strA hasSuffix:strB]; BOOL isContain = [strA rangeOfString:strB].location != NSNotFound; BOOL isContain = [strA rangeOfString:strB options:NSCaseInsensitiveSearch].location != NSNotFound;
C#: bool empty = string.IsNullOrEmpty(value); bool empty = string.IsNullOrWhiteSpace(value); Objective-C: BOOL empty = (value == nil || value.length == 0); BOOL empty = (value == nil || value.length == 0 || [[value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0); // 同IsNullOrWhiteSpace
C#: string name = value.ToLower(); string name = value.ToUpper(); Objective-C: NSString *name = [value lowercasestring]; NSString *name = [value uppercasestring];
C#:
float x = 2.43534f;
string s = x.ToString(“n2″);
string s = string.Format("{0} {1}", "lwme", "cnblogs");
Objective-C:
float x = 2.34454f;
NSString *s = [NSString stringWithFormat: @"%.2f", x];
NSString *s = [NSString stringWithFormat: @"%@ %@", @"lwme", @"cnblogs"];
objc和C#一样,字符串都是不可变的,要改变字符串则分别需要使用StringBuilder、NSMutableString。
C#:
StringBuilder builder = new StringBuilder(20);
builder.Append("lwme");
builder.AppendFormat(".{0}.{1}", "cnblogs", "com");
Objective-C:
NSMutableString *builder = [NSMutableString stringWithCapacity:20];
[builder appendString:@"lwme"];
[builder appendFormat:@".%@.%@", @"cnblogs", @"com"];
C#:
string[] data = {};
string[] data = {"one", "two"};
Objective-C:
// 旧语法
NSArray* data = [NSArray arrayWithObjects:@"one", @"two", nil]; // (定义数组时用逗号分隔对象列表,并且必须以nil结尾)
// objc 2.0新语法
NSArray *data = @[]; //空数组
NSArray* data = @[@"one", @"two"];
C#: data.Length Objective-C: [data count] data.count
C#: data[0] data[0]="two"; Objective-C: [data objectAtIndex:0] data[0] // objc 2.0 新语法 data[0]=@"two";
C#:
int index = data.IndexOf("one");
Objective-C:
int index = [data indexOfObject:@"one"];
C#: foreach (string item in array) ... Objective-C: for (NSString *item in array) ...
objc和C#一样,数组是不可变的,如果需要改变数组的元素,则分别要用到List<T>、NSMutableArray。
C#:
List<string> list = new List<string>();
List<string> list = new List<string>(20);
List<string> list = new List<string> { "lwme", "cnblogs" };
list.Add("lwme");
list.AddRange(new[] { "l", "w", "m", "e" });
list.Insert(0, "lwme");
list.Remove("lwme");
list.RemoveAt(0);
list.Clear();
bool isContain = list.Contains("lwme");
bool isContain = list.Contains("lwme", StringComparer.InvariantCultureIgnoreCase);
Objective-C:
NSMutableArray *list = [NSMutableArray array];
NSMutableArray *list = [NSMutableArray arrayWithCapcity: 20];
NSMutableArray *list = [@[@"lwme", @"cnblogs"] mutableCopy];
[list addObject:@"lwme"];
[list addObjectsFromArray:@[@"lwme, @"cnblogs"]];
[list insertObject:@"lwme", atIndex:0];
[list removeObject:@"lwme"];
[list removeObjectAtIndex:0];
[list removeAllObjects];
BOOL isContain = [list containsObject:@"lwme"];
在objc中有不可变的字典NSDictionary,在C#中没有对应的,而可变的字典NSMutableDictionary对应C#中的Dictionary<TKey,TValue>。
C#:
Dictionary<string, string> dict = new Dictionary<string, string>();
Dictionary<string, string> dict = new Dictionary<string, string>(20);
Dictionary<string, string> dict = new Dictionary<string, string> { {"name", "lwme"}, {"host", "cnblogs"} };
dict.Add("name", "lwme");
dict["name"] = "lwme";
dict.Remove("name");
dict.Clear();
dict.ContainsKey("name");
string name = dict["name"]; // dict.TryGetValue("name", out ...)
Objective-C:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: @"lwme", 0, @"cnblogs", 1, nil]; // 旧语法
NSDictionary *dict = @{0: @"lwme", 1: @"cnblogs"}; // objc2.0语法
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity: 20];
NSMutableDictionary *dict = [@{0: @"lwme", 1: @"cnblogs"} mutableCopy];
[dict setObject:@"lwme" forKey:@"name"];
[dict removeObjectForKey:@"name"];
[dict removeAllObjects];
BOOL isContain = [[dict allKeys] containsObject:@"name"];
BOOL isContain = [dict objectForKey:@"name"] != nil;
NSString *name = [dict objectForKey:@"name"];
NSString *name = dict[@"name"];
objc中有c语言的基本类型如int、float、struct等,还有它们的封装类型NSNumber,由于NSNumber只能存储对象,不能存储任何基本类型,所以这些基本类型需要用NSNumber来包装。
C#: int ii = 1; long li = 1; float fi = 1.1; double di = 1.1; bool b = true; Objective-C: int ii = 1; long li = 1; float fi = 1.1; double di = 1.1; bool b = true; BOOL b = YES; NSNumber ii = [NSNumber numberWithInt: 1]; NSNumber li = [NSNumber numberWithLong: 1]; NSNumber fi = [NSNumber numberWithFloat: 1.1]; NSNumber di = [NSNumber numberWithDouble: 1.1]; NSNumber b = [NSNumber numberWithBOOL: YES]; NSNumber ii = @1; NSNumber li = @1; NSNumber fi = @1.1; NSNumber di = @1.1; NSNumber b = @YES;
objc的类分成.h头文件和.m实现文件,.h头文件里定义所有公开的方法、属性、字段,.m实现文件里实现公开的方法以及私有的字段、方法。
C#:
public class Person
{
private int privateField;
public int Age {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
public Person(int age) {
this.Age = age;
this.OnAgeChange(age);
}
private void OnAgeChange(int age) {
}
public string GetFullName() {
return this.FirstName + " " + this.LastName;
}
public void SetFullName(string firstName, string lastName) {
this.FirstName = firstName;
this.LastName = lastName;
}
public virtual void PrintAge(){
Console.WriteLine("{0}", this.Age);
}
public static Person CreatePerson(int age) {
return new Person(age);
}
}
Objective-C:
Person.h:
@interface Person : NSObject
-(id)initWithAge:(int)age; // 构造器
@property(nonatomic) int age; // 属性
@property(nonatomic) NSString *firstName;
@property(nonatomic) NSString *lastName;
-(NSString*)getFullName; // 方法
-(void)setFullName:(NSString *)firstName andLastName:(NSString *)lastName;
-(void)printAge;
+(id)createPersonWithAge:(int)age;
@end
Person.m:
@interface Person()
{
int _privateField; // 私有字段
}
@end
@implementation Person
@synthesize age, firstName, lastName;
-(id)initWithAge:(int)age
{
if(self = [super init])
{
self.age = age;
[self onAgeChange:age];
}
return self;
}
-(void)onAgeChange:(int)age
{
}
-(NSString*)getFullName
{
return [NSString stringWithFormat:"%@ %@", self.firstName, self.lastName];
}
-(void)setFullName:(NSString *)firstName andLastName:(NSString *)lastName
{
self.firstName = firstName;
self.lastName = lastName;
}
-(void)printAge
{
NSLog(@"%i", self.age);
}
+(id)createPersonWithAge:(int)age
{
return [[Person alloc] initWithAge:age];
}
@end
C#:
Person p = new Person(11);
Person p = Person.CreatePerson(11);
p.setFullName("lwme", "cnblogs");
p.FirstName = "lwme";
p.PrintAge();
string fullName = p.GetFullName();
int age = p.Age;
Objective-C:
Person *p = [[Person alloc] initWithAge:11];
Person *p = [Person CreateWithAge:11];
[p setFullName:@"lwme" andLastName:@"cnblogs"];
p.firstName = @"lwme";
[p PrintAge];
NSString *fullName = [p getFullName];
int age = p.Age;
C#:
public class ChildPerson: Person
{
public ChildPerson(int age): base(age){}
public override void PrintAge() {
base.PrintAge();
Console.WriteLine("print age in childperson");
}
}
Objective-C:
ChildPerson.h
@interface ChildPerson:Person
@end
ChildPerson.m
@interface ChildPerson()
@end
@implementation ChildPerson
-(void)printAge
{
[super printAge];
NSLog(@"print age in childperson");
}
@end
C#: ChildPerson p = new ChildPerson(11); string val = p.ToString(); Objective-C: ChildPerson *p = [[ChildPerson alloc] initWithAge:11]; NSString *val = [p description];
objc中的协议可以对应C#中的接口、事件,其中事件一般声明为delegate名称的属性,在使用的时候只需要设置delete就可以绑定所有事件。
C#
public interface IEquatable<T>
{
bool Equals(T obj);
}
public class Person : IEquatable<MyClass>
{
public Action<Person> onAgeChanged;
public int Age { get; set; }
public bool Equals(Person p)
{
return p.Age == this.Age;
}
public void SetAge(int age) {
this.Age = age;
if (onAgeChanged != null)
onAgeChanged(this);
}
}
Objective-C
@protocol IEquatable
@required
-(bool)equals: (Person*)obj;
@end
@protocol IChangeAction
@optional
-(void)onAgeChange: (Person*)obj;
@end
@interface Person : NSObject<IEquatable>
@property(nonatomic) int age;
@property(nonatomic, weak)id<IChangeAction> delegate;
-(void)setAge:(int)age;
@end
@implementation Person
@synthesize age;
-(bool)equals:(Person*)p
{
return p.age == self.age;
}
-(void)setAge:(int)age
{
self.age = age;
if ([self.delegate respondsToSelector:@selector(onAgeChange:)])
[self.delegate onAgeChange:self];
}
@end
C#
public enum Orientation: uint {
Vertical = 0,
Horizontal = 1
}
Objective-C
typedef enum Orientation : NSUInteger {
OrientationVertical = 0,
OrientationHorizontal = 1
} Orientation;
C#
public Orientation TextAlignment {get;set} // 属性
label.TextAlignment = Orientation.Horizontal;
Objective-C
@property(nonatomic, assign) Orientation textAlignment;
label.textAlignment = OrientationHorizontal;
C#: Type t = typeof(Person); Objective-C: Class c = [Person class];
C#: Person p = new Person(); Type t = p.GetType(); Objective-C: Person *p = [[Person alloc] init]; Class c = p.class;
C#: string name = type.Name; string name = typeof(Person).Name; Objective-C: NSString *name = NSStringFromClass(p.class); NSString *name = NSStringFromClass([Person class]);
C#: bool isPerson = p is Person; Objective-C: BOOL isPerson = [p isKindOfClass:c];
C#: bool isInherited = p is Person; bool isInherited = p.GetType().IsSubclassOf(typeof(Person)); bool isInherited = typeof(ChildPerson).IsSubclassOf(typeof(Person)); bool isInherited = typeof(Person).IsAssignableFrom(typeof(ChildPerson)); Objective-C: BOOL isInherited = [[p class] isSubclassOfClass:[Person class]]; BOOL isInherited = [[ChildPerson class] isSubclassOfClass:[Person class]];
C#: bool isImplemented = p is IEquatable; bool isImplemented = typeof(IEquatable<>).IsAssignableFrom(p.GetType()); bool isImplemented = typeof(IEquatable<>).IsAssignableFrom(typeof(Person)); bool isImplemented = typeof(Person).GetInterfaces().Contains(typeof(IEquatable<>)); Objective-C: BOOL isImplemented = [p class conformsToProtocol:@protocol(IEquaatable)];
C#: object instance = Activator.CreateInstance(Type.GetType("ChildPerson")); Objective-C: id instance = [[NSClassFromString("ChildPerson") alloc] init];
C#:
MethodInfo method = type.GetMethod("PrintAge");
bool hasMethod = method != null;
method.Invoke(p, null);
Objective-C:
SEL method = @selector(printAge);
BOOL hasMethod = [p respondsToSelector: method];
[p performSelector:method];
C#:
object age = p.GetType().GetProperty(“Age”).GetValue(p, null);
foreach(PropertyInfo pi in typeof(Person).GetProperties())
{
// pi.Name
}
Objective-C:
id age = [p valueForKey:@"Age"];
unsigned int propertyCount = 0;
objc_property_t * properties = class_copyPropertyList([Person class], &propertyCount);
for (unsigned int i = 0; i < propertyCount; ++i) {
objc_property_t property = properties[i];
const char * name = property_getName(property);
}
free(properties);
objc里的Category可以很好的实现C#中的扩展方法。
C#
public static class PersonExtension {
public static void PrintFullName(this Person p) {
Console.WriteLine(p.GetFullName());
}
}
Objective-C
Person+PrintExtension.h
#import "Person.h"
@interface Person (PrintExtension)
-(void)PrintFullName;
@end
Person+PrintExtension.m
@implementation Person (PrintExtension)
-(void)PrintFullName
{
NSLog(@"%@", [self getFullName]);
}
@end
C#
try {
} catch (Exception ex) {
} finally {
}
Objective-C
@try {
}
@catch (NSException *exception) {
}
@finally {
}
objc没有命名空间机制,直接从包或者当前项目引入头文件即可。
C# using System; using System.Text; using MyCompany.CustomNamespace; Objective-C #import <UIKit/UIKit.h> #import <Foundation/Foundation.h> #import "CustomClass.h"
objc中有ARC机制对应.net 中的GC,详细的可以看:http://snakcakeblog.tumblr.com/post/47765862590/grudge-match-c-gc-vs-objective-c-arc
在C#当中,源代码一般被编译成程序集,而在objc中,都是编译成静态链接库,而且引用方式也不相同。
http://www.infragistics.com/community/blogs/stevez/archive/2013/05/09/c-to-objective-c-the-ultimate-guide.aspx(本文内容主要来自它,并做了一些更改)
http://developer.apple.com/library/ios/#referencelibrary/GettingStarted/RoadMapiOSCh/chapters/Introduction.html
http://www.anotherchris.net/csharp/objective-c-by-example-for-a-csharp-developer/
http://www.cnblogs.com/chijianqiang/archive/2012/06/22/objc-category-protocol.html
http://www.techotopia.com/index.php/Working_with_String_Objects_in_Objective-C
http://overooped.com/post/41803252527/methods-of-concurrency