2012-05-10 32 views
5

Ran vào một vấn đề thú vị mà tôi đã tự hỏi nếu có ai có thể giúp giải thích. Tôi đã thử tìm kiếm trên internet và dường như không tìm thấy câu trả lời cho vấn đề này. Trong khi chúng tôi có một giải pháp, những người khác có thể chạy vào cùng một vấn đề, và vì nó là ngẫu nhiên, rất khó để theo dõi.Marshalling "như chuỗi" tham số từ C#

Chúng tôi có một ứng dụng ngẫu nhiên không thành công khi máy tính được kết nối với mạng công ty của khách hàng (không có nhiều thông tin trên mạng). Khi chúng tôi đưa máy tính vào môi trường của chúng tôi, nó hoạt động tốt. Thất bại là khá ngẫu nhiên, nhưng tốt nhất là tôi có thể tìm ra xảy ra trong các cuộc gọi từ C# đến một nhà cung cấp bên thứ ba không được quản lý DLL. Một trong những dấu vết sao tôi có (chỉ có một vài thất bại cung cấp dấu vết trong bản ghi sự kiện hệ thống) điểm đến một thất bại trong ntdll.dll trong các chức năng RtlMoveMemory trong marshalling các tham số trong các cuộc gọi đến DLL không được quản lý.

Cuộc gọi đến hàm không được quản lý là:

ThirdParty.CxxxAutomationWrapper clientDLL = new ThirdParty.CxxxAutomationWrapper() ; 

object Parameter1 ; 
    : 
string theValue = "abcde" ; 
Parameter1 = theValue ; 
    : 
if (Parameter1 is string) 
{ 
    int returnCode = clientDLL.function (Parameter1 as string) ; 
} 

Cuộc gọi định kỳ không thành công trên máy tính khách hàng nhưng luôn luôn hoạt động khi chạy trong Visual Studio (2010). Giá trị của Parameter1 được đặt chính xác (không bao giờ null).

Kể từ khi tôi đã thay đổi cuộc gọi đến:

String parameter1String = Parameter1.ToString() ; 
int returnCode = clientDLL.function (parameter1String) ; 

tất cả mọi thứ đã làm việc tốt. Giá trị của Parameter1 được kiểm soát và không phải là null trước khi mã này được thực hiện.

Giao diện được gọi là (clientDLL.function) được định nghĩa là: [? Giới hạn]

HRESULT function ([in] BSTR parameter, 
        [out, retval] long *ret); 

Với tôi hiểu biết về 'là' tuyên bố trong C#, tôi không hiểu tại sao phiên bản đầu tiên của điều này không thành công. Ai có thể giúp giải thích tại sao điều này không thành công khi được gọi với tham số được chỉ định là "như chuỗi"?

+0

Đã cập nhật bài đăng gốc để trả lời các câu trả lời mà tôi đã nhận được để giúp làm rõ vấn đề. Các cập nhật bao gồm hiển thị Parameter1 được khai báo và gán như thế nào, và đặt một if (Parameter1 là string) xung quanh cuộc gọi như được đề xuất bởi Tudor. –

+0

Bạn có thể thử đăng nhập xem giá trị nào của 'Parameter1' xảy ra không? Bạn có thể thấy bất kỳ mẫu nào không? – Tudor

+0

Tôi đã mã hóa mã chính xác được hiển thị ở trên, mã hóa gán cho biến chuỗi khởi tạo nó bằng "abcde" và gán biến đó cho Parameter1 kiểm tra nó qua if (Parameter1 là string) và nó vẫn hoạt động tốt trong Visual Studio nhưng không thành công của VS (đôi khi). –

Trả lời

5

obj as stringobj.ToString() không giống nhau. Đầu tiên là một dàn diễn viên cố gắng (loại giống như (string)obj, nhưng trả về null khi không thành công), trong khi giây là một cuộc gọi phương thức trả về một biểu diễn chuỗi của đối tượng.

Thực tế bạn có thể nhận được biểu diễn chuỗi của bất kỳ đối tượng bất kể nó tương thích với chuỗi như kiểu, nhưng dàn diễn viên sẽ thất bại nếu chúng không tương thích.

ví dụ đơn giản:

object obj = new object(); // simple object 
Console.WriteLine(obj.ToString()); // prints System.Object 
Console.WriteLine((obj as string) == null); // True: obj is not a string! 
+0

Tôi đã cập nhật mã mẫu của mình để cho thấy rằng Parameter1 luôn chứa đối tượng chuỗi hợp lệ. Ngoài ra tôi đang gặp rắc rối với các ngẫu nhiên-Ness của lỗi và thực tế là không có một vấn đề đang chạy trong Visual Studio. –

+0

@RichardBousman: Vì vậy, bạn chắc chắn rằng 'Parameter1' luôn là một chuỗi hợp lệ? Tôi có thể thấy tình huống mà bạn đã đề cập xảy ra trong trường hợp bạn đôi khi đi qua một chuỗi không nhầm lẫn, chẳng hạn như 'là chuỗi' không thành công, nhưng' ToString' thì không. – Tudor

+0

Có. Nếu nó không được, tôi tin rằng nó sẽ 1) luôn luôn thất bại 2) thất bại trong Visual Studio. Tham số được kiểm tra nhiều lần trước thời điểm này. Mã được tham chiếu ở trên là trong một DLL. Mã này nằm trong một DLL được quản lý. Chuỗi ban đầu được chuyển vào DLL được quản lý từ một DLL C++ không được quản lý. –

2

Parameter1.ToString() sẽ làm cho bất kỳ đối tượng .NET thành một chuỗi (ví dụ trường hợp của System.String). Parameter1 as string sẽ trả về null nếu Parameter1 là null hoặc nếu nó không phải là một ví dụ của System.String. Nếu đó là lớp kết thúc tốt hơn một chuỗi thay vì thực sự là một, thì bạn sẽ kết thúc bằng một số null.

Sẽ không hoạt động trong mọi trường hợp. Nếu bạn có một phiên bản System.Stringnull, thì Parameter1 as string sẽ trả lại chính xác null, trong khi Parameter1.ToString() sẽ ném một số NullReferenceException.

Cách tiếp cận an toàn sẽ là: Convert.ToString(Parameter1).

+0

Cảm ơn bạn đã phản hồi. Tôi đã cập nhật bài đăng gốc để cho thấy rằng Parameter1 luôn là một chuỗi hợp lệ. –

0

Parameter1 as string có thể được coi như

string foo 
try 
{ 
    foo = (string)Parameter1; 
} 
catch 
{ 
    foo = null; 
} 

nơi .ToString()

string foo = Parameter1.ToString(); 

Thực tế là argument1 không cast được trực tiếp đến một chuỗi là reson cho nó thất bại.

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