C#自定义属性参数

时间:2016-10-15 15:26:00

标签: c# parameter-passing

我在这个链接Adding parameters to custom attributes中看到了如何在自定义属性

上添加参数的答案
import UIKit
import QuartzCore

class ViewController: UIViewController {

static let kMargin:CGFloat = 10.0;

override func viewDidLoad()
{
super.viewDidLoad()

// create a container view that all of our subviews for which we want to detect touches are:

let containerWidth = fmin(self.view.bounds.size.width, self.view.bounds.size.height) - ViewController.kMargin * 2.0

let container = UIView(frame: CGRect(x: ViewController.kMargin, y: ViewController.kMargin, width: containerWidth, height: containerWidth))
container.backgroundColor = UIColor.darkGray
    view.addSubview(container)

// now create all of the subviews, specifying a tag for each; and

let cellWidth = (containerWidth - (4.0 * ViewController.kMargin)) / 3.0

    for column in 0 ..< 3 {
        for row in 0 ..< 3 {
            let cell = UIView(frame: CGRect(x: ViewController.kMargin + CGFloat(column) * (cellWidth + ViewController.kMargin), y: ViewController.kMargin + CGFloat(row) * (cellWidth + ViewController.kMargin), width: cellWidth, height: cellWidth))
            cell.tag = row * 3 + column;
            container.addSubview(cell)
        }
    }

// finally, create the gesture recognizer

    let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
    container.addGestureRecognizer(pan)

}

// Here's a Swift 3.0 version based on Rajesh Choudhary's answer:

func drawLine(onLayer layer: CALayer, fromPoint start: CGPoint, toPoint end:CGPoint) {
    let line = CAShapeLayer()
    let linePath = UIBezierPath()
    linePath.move(to: start)
    linePath.addLine(to: end)
    line.path = linePath.cgPath
    line.fillColor = nil
    line.lineWidth = 8
    line.opacity = 0.5
    line.strokeColor = UIColor.red.cgColor
    layer.addSublayer(line)
}

var gesturedSubviews : [UIView] = []
var startX: CGFloat!
var startY: CGFloat!
var endX: CGFloat!
var endY: CGFloat!

func handlePan(gesture: UIPanGestureRecognizer) {

if (gesture.state == .began)
{
    gesturedSubviews = [];
    let location = gesture.location(in: gesture.view)
    print("location \(location)")
    startX = location.x
    startY = location.y
  }
  if (gesture.state == .changed) {
    let location = gesture.location(in: gesture.view)
    print("location \(location)")
    endX = location.x
    endY = location.y
    drawLine(onLayer: view.layer, fromPoint: CGPoint(x: startX, y: startY), toPoint: CGPoint(x:endX, y:endY))
    startX = endX
    startY = endY
}
if (gesture.state == .ended) {
        let location = gesture.location(in: gesture.view)
        print("location \(location)")
        drawLine(onLayer: view.layer, fromPoint: CGPoint(x: startX, y: startY), toPoint: CGPoint(x:location.x, y:location.y))
}

// now figure out whether:
//   (a) are we over a subview; and
//   (b) is this a different subview than we last were over

 let location = gesture.location(in: gesture.view)
    print("location \(location)")

    for subview in (gesture.view?.subviews)! {
        if  subview.frame.contains(location) {
                if (subview != gesturedSubviews.last) {

                gesturedSubviews.append(subview)

                subview.backgroundColor = UIColor.blue
                subview.alpha = 1.0

            }
        }
    }
}

}

现在我想知道是不是可以写这样的?

class MyCustomAttribute : Attribute {
    public int[] Values { get; set; }

    public MyCustomAttribute(params int[] values) {
       this.Values = values;
    }
}

[MyCustomAttribute(3, 4, 5)]
class MyClass { }

我将属性值更改为变量_values。 我也将它设为私有,当我尝试它时它工作正常。

有人可以告诉我为什么接受的答案是有效的吗?

3 个答案:

答案 0 :(得分:7)

接受的答案使用公共财产而不是私人字段。公共属性的好处是你可以省略构造函数并在默认构造函数中提供属性的值。

我将您的第一个代码(具有公共属性的代码)更改为此类代码。

class MyCustomAttribute : Attribute {
    public int[] Values { get; set; }
}

[MyCustomAttribute(Values = new int[] { 3, 4, 5 })]
class MyClass { }

答案 1 :(得分:4)

对于[MyCustomAttribute(3, 4, 5)],参数列表是未命名的,因此使用了MyCustomAttribute的构造函数。

因此,如果存在公共Values属性,则无关紧要。

在您的第一个代码示例中,可以使用[MyCustomAttribute(3, 4, 5)][MyCustom(Values = new[] {3, 4, 5})]

第二个代码示例&#34;仅&#34;接受[MyCustomAttribute(3, 4, 5)]

答案 2 :(得分:2)

存在差异,而且全部都是reflection

主要是我们得到的流畅性 - 我们可以使用构造函数或Values属性。

enter image description here

public class MyCustomAttribute : Attribute
{
    public int[] Values { get; set; } = new int[] { 1, 2, 3 };

    public MyCustomAttribute(params int[] values)
    {
        this.Values = values;
    }
}

[MyCustom(1, 2, 3)]
class MyClass
{

}

[MyCustom(Values = new int[] { 1, 2, 3})]
public class MyAnotherClass
{
}

获得财产的另一个因素是reflection;如果Values字段为public,我们可以使用以下内容获取详细信息,但不能使用private

var data = typeof(MyCustomAttribute).GetProperty("Values");