2010-05-04 64 views
6

Theo như tôi biết, bạn không thể chuyển các tham số tới một hàm tạo tĩnh trong C#. Tuy nhiên tôi có 2 tham số cần truyền và gán chúng cho các trường tĩnh trước khi tạo một thể hiện của một lớp. Làm thế nào để tôi đi về nó?Truyền các tham số tĩnh đến một lớp

+6

Sẽ giúp ích nếu bạn có thể xác định "tham số tĩnh" - đó không phải là thuật ngữ tôi quen thuộc ... –

+0

@Jon: Tôi cho rằng họ muốn chuyển đối số vào một hàm tạo tĩnh. Mà không làm việc, tất nhiên, nhưng tôi thấy nó để họ muốn tĩnh khởi tạo một trường tĩnh của lớp với dữ liệu thông qua trong thời gian chạy. – Joey

+3

@Johannes: Điều làm tôi bối rối là nơi OP mong đợi truyền chúng * từ *. Không giống như các hàm tạo mẫu, các hàm tạo tĩnh không phải là "được gọi" - chúng chỉ thực thi tại thời điểm thích hợp. Tôi hy vọng rằng nếu OP làm rõ những gì họ thực sự muốn đạt được, câu trả lời có thể trở nên rõ ràng hơn. –

Trả lời

6

Đây có thể là một lời kêu gọi ... Một phương thức factory!

class Foo 
{ 
    private int bar; 
    private static Foo _foo; 

    private Foo() {} 

    static Foo Create(int initialBar) 
    { 
    _foo = new Foo(); 
    _foo.bar = initialBar; 
    return _foo; 
    } 

    private int quux; 
    public void Fn1() {} 
} 

Bạn có thể muốn đặt dấu kiểm 'thanh' đã được khởi tạo (hoặc không) nếu thích hợp.

+1

Điều này làm gì mà không thể đạt được bằng cách chuyển đối số 'initialBar' đến một instance constructor? – LukeH

+0

Trong ví dụ này, không có gì. Nhưng nó giải quyết câu hỏi của anh ấy, Không biết nhiều hơn về tình hình cụ thể của anh ấy, đó là điều tốt nhất tôi có thể làm. – AlfredBr

+0

@AlfredBr: Không thể truy cập trường mẫu _foo tạo thành một phương thức tĩnh và không thể truy cập vào trường "thanh" tĩnh từ một cá thể của Foo, khi mã của bạn thử. Tôi không hiểu giải pháp của bạn chút nào. –

2

Tôi giả sử bạn có nghĩa là thành viên tĩnh của một lớp học? Trong trường hợp đó, bạn có thể làm điều này:

public class MyClass 
{ 
    public static int MyInt = 12; 
    public static MyOtherClass MyOther = new MyOtherClass();  
} 

Những thành viên tĩnh được đảm bảo để được khởi tạo trước khi bất kỳ lớp được khởi tạo.

Nếu bạn cần logic phức tạp, làm điều đó trong một constructor tĩnh:

public class MyClass 
{ 
    public static int MyInt; 
    public static MyOtherClass MyOther; 
    static MyClass() 
    { 
     MyInt = 12; 
     MyOther = new MyOtherClass(); 
    } 
} 

Sửa

Dựa trên chỉnh sửa của bạn, tôi muốn nói chỉ gán các giá trị cho những gì họ cần phải được trước khi bạn khởi tạo lớp học, như vậy:

public class MyClass 
{ 
    public static int MyInt; 
    public static MyOtherClass MyOther; 
} 

// elsewhere in code, before you instantiate MyClass: 
MyClass.MyInt = 12; 
MyClass.MyOther = new MyOtherClass(); 
MyClass myClass = new MyClass(); 

Điều đó cho biết, phương pháp này không đảm bảo rằng MyInt và MyOther được đặt trước MyCl ass được khởi tạo. Nó sẽ hoạt động, nhưng đòi hỏi kỷ luật trước khi khởi tạo MyClass.

Một mô hình thay thế, bạn có thể làm theo vẻ bề ngoài như thế này:

public class MyClass 
{ 
    private static int MyInt; 
    private static MyOtherClass MyOther; 
    private static bool IsStaticInitialized = false; 

    public static InitializeStatic(int myInt, MyOtherClass other) 
    { 
     MyInt = myInt; 
     MyOther = other; 
     IsStaticInitialized = true; 
    } 

    public MyClass() 
    { 
     if(!IsStaticInitialized) 
     { 
      throw new InvalidOperationException("Static Not Initialized"); 
     } 
     // other constructor logic here. 
    } 
} 

// elsewhere in your code: 
MyClass.InitializeStatic(12, new MyOtherClass()); 
MyClass myClass = new MyClass(); 

// alternatiavely: 
MyClass myClass = new MyClass(); // runtime exception. 
+0

đây là cách để intialize các trường tĩnh, nhưng không truyền dữ liệu bên ngoài cho một hàm dựng tĩnh, vì ít nhất trong NET 4, mã xây dựng tĩnh được thực thi trước bất kỳ mã phương thức tĩnh nào và trước khi khởi tạo trường tĩnh. –

+0

bình luận của bạn không chính xác - "Trình khởi tạo biến trường tĩnh của một lớp tương ứng với một chuỗi các phép gán được thực thi theo thứ tự văn bản mà chúng xuất hiện trong khai báo lớp. , việc thực hiện các initializers trường tĩnh xảy ra ngay lập tức trước khi thực hiện constructor tĩnh đó. Nếu không, các initializers trường tĩnh được thực hiện tại một thời gian thực hiện phụ thuộc trước khi sử dụng đầu tiên của một trường tĩnh của lớp đó. được nói tại: https://msdn.microsoft.com/en-us/library/aa645758(v=vs.71).aspx –

4

Bạn không thể chuyển tham số cho một hàm tạo tĩnh, nhưng bạn có thể chuyển tham số cho chính lớp đó - thông qua các tham số kiểu chung.

Hơi điên ý tưởng này, tuy nhiên, tôi sẽ chỉ ném nó ra khỏi đó.

Làm cho lớp chung (với TypeParam cung cấp kiểu tham số) và đặt các ràng buộc chung trên nó (chi tiết trong ví dụ mã), sau đó lấy một kiểu tham số mới, chứa các virtual mà bạn có thể sử dụng để đọc chúng muốn các giá trị tham số được.

//base parameter type - provides the 'anchor' for our generic constraint later, 
//as well as a nice, strong-typed access to our param values. 
public class StaticParameterBase 
{ 
    public abstract string ParameterString{ get; } 
    public abstract MyComplexType ParameterComplex { get; } 
} 

//note the use of the new() generic constraint so we know we can confidently create 
//an instance of the type. 
public class MyType<TParameter> where TParameter:StaticParameterBase, new() 
{ 
    //local copies of parameter values. Could also simply cache an instance of 
    //TParameter and wrap around that. 
    private static string ParameterString { get; set; } 
    private static MyComplexType ParameterComplex { get; set; } 

    static MyType() 
    { 
    var myParams = new TParameter(); 
    ParameterString = myParams.ParameterString; 
    ParameterComplex = myParams.ParameterComplex; 
    } 
} 

//e.g, a parameter type could be like this: 
public class MyCustomParameterType : StaticParameterBase 
{ 
    public override string ParameterString { get { return "Hello crazy world!"; } } 
    public override MyComplexType { get { 
     //or wherever this object would actually be obtained from. 
     return new MyComplexType() { /*initializers etc */ }; 
    } 
    } 
} 

//you can also now derive from MyType<>, specialising for your desired parameter type 
//so you can hide the generic bit in the future (there will be limits to this one's 
//usefulness - especially if new constructors are added to MyType<>, as they will 
//have to be mirrored on this type as well). 
public class MyType2 : MyType<MyCustomParameterType> { } 

//then you'd use the type like this: 
public static void main() 
{ 
    var instance = new MyType<MyCustomParameterType>(); 
    //or this: 
    var instance2 = new MyType2(); 
} 

Tôi đã xem xét giải pháp sử dụng thuộc tính loại tùy chỉnh áp dụng cho thông số loại, tuy nhiên đây có thể là cách tốt hơn. Tuy nhiên, bây giờ bạn sẽ sử dụng lớp của bạn luôn với một kiểu tham số chung (trừ khi bạn có thể sử dụng thủ thuật đặc biệt deritting +) - có thể quá vụng về theo ý thích của bạn.

Tôi cũng thích điều này hơn các giải pháp khác được trình bày ở đây vì nó không yêu cầu tạo bất kỳ giải pháp nào cho khởi tạo tĩnh - bạn vẫn có thể sử dụng bảo đảm duy nhất của .Net.

Cảnh báo - bạn có nên xem xét cấu trúc của mình không?

Tất cả những gì đã nói - hãy nhớ, vì bạn chỉ có thể tham số tĩnh một lần (hoặc trong trường hợp này, mỗi kiểu tĩnh duy nhất được tham số hóa chung) - Tôi sẽ tự hỏi tại sao không chỉ kéo mã nhận các tham số cho tĩnh, và đặt nó trong constructor tĩnh ở nơi đầu tiên? Bằng cách đó bạn không thực sự phải sử dụng các mẫu kỳ lạ như thế này!

+1

WOW! (Cười, vì tôi đã học được điều gì đó mới mẻ!) – AlfredBr

+0

@AlfredBr - tuyệt, có thể hữu ích một ngày! U không may, mặc dù, nó đến với mã như thế này mà đôi khi làm cho nó khó khăn cho tôi để có được một số thành phần của tôi được chấp nhận bởi bất cứ ai trong nhóm của tôi khác hơn so với các lập trình viên hardcore nhất! c'est la vie! –

+0

@AndrasZoltan: giải pháp của bạn hoạt động và đã thực hiện có thể trong ngày !!! Hôm nay là ngày giải pháp của bạn hữu ích cho tôi. Đó là điên rồ điên rồ, như bạn nói, nhưng nó là một cách để vượt qua dữ liệu bên ngoài để một nhà xây dựng tĩnh. Cảm ơn –

Các vấn đề liên quan