5
5

More than 5 years have passed since last update.

Swift vs. C#: Properties

Posted at
  • Computed Properties & Stored Properties

Stored Properties

Swift:

  • Class & Strucutreに“所有される構成要素”
  • variable stored properties(var)
  • constant stored properties(let)

C#:

  • Field (const, readonly...)
  • Property

Stored Properties of Constant Structure Instances

Swift:

  1> struct Point{ var x = 0 ; let y = 0 } 
  2> var p = Point()
p: Point = {
  x = 0
  y = 0
}
  3> p.x = 10
  4> p.y = 10
/var/folders/3n/0lk686q1129clzkw38blpwdc0000gp/T/lldb/66693/repl7.swift:2:5: error: cannot assign to 'y' in 'p'
p.y = 10
~~~ ^

C#: そもそも constはインスタンスではなくてクラスのスコープ

  • struct はパラメータ初期化のコンストラクタを明示的に宣言する必要がある
csharp> public struct Point {      
      >   public int x ;           
      >   public const int y=0;
      >   public Point(int x ) { this.x = x ; } // 必須
      > };
csharp> var p = new Point(0);
csharp> p.y
(1,4): error CS0176: Static member `Point.y' cannot be accessed with an instance reference, qualify it with a type name instead
csharp> Point.y
0
csharp> p.x = 10
csharp> p.x
10

Swift: structインスタンスをletで定数にできる

  4> let pf = Point()
pf: Point = {
  x = 0
  y = 0
}
  5> pf.x = 10
/var/folders/3n/0lk686q1129clzkw38blpwdc0000gp/T/lldb/66693/repl11.swift:2:6: error: cannot assign to 'x' in 'pf'
pf.x = 10
~~~~ ^

C#: structインスタンスをreadonlyで定数にできる

csharp> public class Container {
      >    public const Point Origin = new Point(0);
      > }
(2,23): error CS0283: The type `Point' cannot be declared const
csharp> public class Container {
      >    public readonly Point Origin = new Point(0);
      > }
csharp> var c = new Container();
csharp> c.Origin.x = 100;
(1,11): error CS1648: Members of readonly field `Container.Origin' cannot be modified (except in a constructor or a variable initializer)
csharp> var p2 = c.Origin;
csharp> p2.x = 100;
csharp> p2.x
100

Lazy Stored Properties

A lazy stored property is a property whose initial value is not calculated until the first time it is used.

You indicate a lazy stored property by writing the lazy modifier before its declaration.

Swift:

  6> class Container { 
  7.     lazy var position = Point() 
  8. }    
  9> var c = Container()
c: Container = {
  position.storage = nil
}
 10> c.position.x
$R0: Int = 0
 11> c
$R1: Container = {
  position.storage = (x = 0, y = 0)
}

C#: Propertyを使う

public class Point 
{
  public int x;
  public const int y = 0;
}

public class Container {
  public Point _pos=null;
  public Point Position {
    get {
      this._pos = this._pos ?? new Point();
      return this._pos;
    }
  }
}
        var c = new Container();
        Assert(c._pos == null );        
        Assert(c.Position.x == 0 );
        Assert(c._pos != null );        

Stored Properties and Instance Variables

Objective-Cでの値の持ち方

  • プロパティ
  • インスタンス変数をバッキングストアとして使う

Swiftはプロパティのみ

よくわかっていません。 Computed Propertiesで get/setすればよいということではないのかな?

Computed Properties

Swift:

struct Point { var x = 0.0, y = 0.0 }
struct Size { var width = 0.0, height = 0.0 }

struct Rect {
    var origin = Point()
    var size = Size()
    var center: Point {
        get {
            return Point(
                x: origin.x + (size.width / 2) ,
                y: origin.y + (size.height / 2)
            )
        }
        set(value) {
            origin.x = value.x - (size.width / 2)
            origin.y = value.y - (size.height / 2)
        }
    }
}

var square = Rect(
        origin: Point(x: 0.0, y: 0.0),
        size: Size(width: 10.0, height: 10.0))

let p1 = square.center
square.center = Point(x: 15.0, y: 15.0)

assert(p1.x != square.center.x)

C#

public struct Point { 
    public double x = 0.0; public double y = 0.0 ;
    public Point(double x, double y)
    { this.x = x; this.y = y; }
}
public struct Size { 
    public double width  = 0.0f; public double height  = 0.0f ;
    public Size(double w, double h)
    { this.width = w; this.height=h;}
}

public struct Rect
{
    public Point origin;
    public Size  size;

    public Point Center 
    {
        get {
            return new Point(
                origin.x + (size.width / 2) ,
                origin.y + (size.height / 2)
            );
        }
        set{
            origin.x = value.x - (size.width / 2.0);
            origin.y = value.y - (size.height / 2.0);
        }
    }
    public Rect(Point p, Size s )
    {
        this.origin =p ; this.size =s ;
    }
}

var square = new Rect( 
    new Point(0.0f, 0.0f), 
    new Size(10.0f, 10.0f));

var p1 = square.Center;
square.Center = new Point(15.0, 15.0);
Console.WriteLine(p1.x == square.Center.x);

False

Shorthand Setter Declaration

Swift: newValue

        set {
            origin.x = newValue.x - (size.width / 2)
            origin.y = newValue.y - (size.height / 2)
        }

C# : value

        set {
            origin.x = value.x - (size.width / 2)
            origin.y = value.y - (size.height / 2)
        }

Read-Only Computed Properties

Swift: setがなければ getの修飾も省略できる

    var readonly_center : Point {
       return center
    }

assert(square.center.x == square.readonly_center.x )

C#: getは省略できない

Property Observers

オブザーバー:

  • willSet is called just before the value is stored.
  • didSet is called immediately after the new value is stored.
  1> struct Point { 
  2.     var x: Int = 0 { 
  3.         willSet(val){ println("setting \(val) to x")} 
  4.         didSet{ println("x is now \(x)")}
  5.     } 
  6. }
  7> var p = Point(x:0)
p: Point = {
  x = 0
}
  8> p.x = 10
setting 10 to x
x is now 10

C# : set の中でやる

    set {
       // do will set
       _x = value;
       // do did set
    } 

C# 6.0: プロパティに初期値をセットできるので

    public int X { get;set; } = x;
    public int Y { get;set; } = y;

Global and Local Variables

Swift: グローバル変数でもいろいろできる

オブザーバー:

  1> var x: Int = 0 { didSet{ println("set to \(x)")} }
x: Int = 0
  2> x = 3
set to 3

get/set: うれしいのだろうか。。。

  1> var x : Int = 0;
x: Int = 0
  2> var y : Int { get{ return 2*x } set { x = 2*newValue }}
y: Int = <computed property>
  3> y
$R0: Int = 0
  4> x = 1
  5> y
$R1: Int = 2
  6> y = 3
  7> x
$R2: Int = 6
  8> y
$R3: Int = 12

C#: 変数はどこかクラスにあって static フィールドにも get/set できる

Type Properties

C#: Static Property

Type Property Syntax / Querying and Setting Type Properties

Swift : struct, enum <- static, class <- class

 19> struct Point { 
 20.     var x = 0 
 21.     var y = 0 
 22.     static var shared = 0 
 23.     static let origin = 0 
 24. }    
 26> var p1 = Point(x:10, y:10)
p1: Point = {
  x = 10
  y = 10
  shared = 140461199908160
  origin = 140461199915776
 28> var p2 = Point(x:100, y:100)
p2: Point = {
  x = 100
  y = 100
  shared = 7365411997647719716
  origin = 3547200665735411558
}
 29> Point.shared = 3 
 30> Point.shared
$R1: Int = 3

 31> Point.origin
$R2: Int = 0

 33> Point.origin = 3
/var/folders/3n/0lk686q1129clzkw38blpwdc0000gp/T/lldb/71998/repl37.swift:2:14: error: cannot assign to the result of this expression
Point.origin = 3
~~~~~~~~~~~~ ^
  • error: class variables not yet supported
  2> class Point { 
  3.     var x = 0 
  4.     var y = 0 
  5.     class var origin  = (0, 0) 
  6. }    
/var/folders/3n/0lk686q1129clzkw38blpwdc0000gp/T/lldb/86707/repl8.swift:5:5: error: class variables not yet supported
    class var origin  = (0, 0)
    ^~~~~
  • 別途ストレージを用意(グローバルとか)
 15> var global_origin = (0, 0)
global_origin: (Int, Int) = {
  0 = 0
  1 = 0
}

 24> class Point { 
 25.     var x = 0 
 26.     var y = 0 
 27.     class var origin :(Int, Int) {  
 28.         get{ return global_origin}  
 29.         set { global_origin = newValue }  
 30.     } 
 31. } 

 50> Point.origin = (100, 100) 
 51.  
 51> Point.origin
$R4: (Int, Int) = {
  0 = 100
  1 = 100
}
  • structはstatic OK
  1> struct Point { 
  2.     static var count = 0 
  3.     var x: Int = 0 { 
  4.         didSet { Point.count++ } 
  5.     } 
  6. }  
  7> var p1 = Point(x:0)
p1: Point = {
  count = 0
  x = -3458755736018865426
}
  8> var p2 = Point(x:0) 
  9. 
p2: Point = {
  count = 0
  x = 8070459310046764983
}
  9> p1.x = 10
 10> p2.x = 20
 11> Point.count
$R0: Int = 2
  • C#
csharp> public class Point {
      >   public static int Count = 0;
      >   protected int _x = 0;
      >   public int X {
      >     get { return _x; }
      >     set { _x = value; Count++; }
      >  }
      > }
csharp> var p1 = new Point();
csharp> var p2 = new Point();
csharp> p1.X = 10;
csharp> p2.X = 20;
csharp> p2.X == p1.X * 2
true
csharp> Point.Count
2
5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5