2015-04-21 35 views
22

Hiện nay mã hóa trong C#, tôi tự hỏi, nếu có một cách để yếu tố mã như trình bày dưới đâyTránh nhiều chức năng cuộc gọi trong C#

Entity1 = GetByName("EntityName1"); 
Entity2 = GetByName("EntityName2"); 
Entity3 = GetByName("EntityName3"); 

Ý tưởng sẽ được để có được một cuộc gọi duy nhất trong các mã, bao thanh toán các mã bằng cách đặt entitiesstrings vào vùng chứa và lặp lại trên vùng chứa này để nhận một dòng "GetByName()" duy nhất. Có cách nào để làm việc này không?

+1

Ngoài thực tế là không có chủ đề để cung cấp mã làm việc, thật khó để cải thiện mã mà không cần thêm thông tin cơ bản. Có lẽ bạn có thể sử dụng một 'Dictionary '. –

+0

Nó phụ thuộc vào cách bạn dự định sử dụng chúng, bạn có thể sử dụng một vòng lặp đơn giản nhưng không rõ ràng những gì bạn mong đợi làm với chúng sau đó – Sayse

+0

er yeah, đó là những gì một vòng lặp cho. – Jodrell

Trả lời

27

Bạn có thể sử dụng LINQ:

var names=new[]{"EntityName1","EntityName2","EntityName3",.....}; 
var entities=names.Select(name=>GetByName(name)).ToArray(); 

Without ToArray, Select sẽ trở lại một IEnumerable sẽ được reevalueated mỗi khi bạn liệt kê nó - đó là, GetByName sẽ được gọi mỗi khi bạn liệt kê các đếm được.

ToArray() hoặc ToList sẽ tạo một mảng (hoặc danh sách) bạn có thể sử dụng nhiều lần.

Bạn cũng có thể gọi ToDictionary nếu bạn muốn để có thể truy cập vào các đối tượng theo tên:

var entities=names.ToDictionary(name=>name,name=>GetByName(name)); 

Tất cả điều này giả định rằng các đối tượng làm chưa tồn tại hoặc GetByName đã làm một số công việc quan trọng để lấy chúng. Nếu các thực thể tồn tại, bạn có thể chỉ cần đặt chúng trong một Dictionary<String,Entity>. Nếu các đối tượng có một tài sản Name bạn có thể sử dụng ToDictionary để tạo ra các từ điển trong một tuyên bố:

var entities=new []{entity1,entity2,entity3,...}; 
var entitiesDict=entities.ToDictionary(entity=>entity.Name,entity=>entity); 
+7

Vậy tại sao không sử dụng một 'Từ điển 'ở nơi đầu tiên, nếu chúng phụ thuộc quá nhiều vào nhau? Sau đó, phương thức 'GetByName', bộ sưu tập' tên' và 'thực thể' và truy vấn LINQ này là thừa. –

+0

@TimSchmelter bạn đang thực hiện một số giả định mặc dù câu hỏi * là * mơ hồ. Tôi giả sử rằng có một số lượng lớn hoặc khác nhau của các tên và OP không muốn có một dòng cho mỗi cuộc gọi - đó là những gì tránh được bởi các tuyên bố LINQ. Tôi cũng giả định rằng thực thể không tồn tại hoặc 'GetByName' thực hiện một số công việc quan trọng để lấy nó. –

+0

@PanagiotisKanavos: và bởi vì bạn cần phải thực hiện các assuptions, câu hỏi này không hề bị ăn đòn. Việc tái cấu trúc mã cũng không chính xác, vì vậy ông có thể đăng nó trên [stackexchange.com] (http://codereview.stackexchange.com/). –

10

Bạn có nghĩa là một cái gì đó giống như bên dưới (nơi entities là bộ sưu tập của Entity1, Entity1 & Entity3):

var results = entities.Select(e => GetByName(e.Name)); 
7

Tùy thuộc vào những gì bạn đang tìm kiếm. Nếu bạn cần đặt các biến trong một dòng, điều đó sẽ không hoạt động. Bạn có thể chơi với sự phản chiếu nếu bạn đang đối phó với các lĩnh vực hoặc tài sản, nhưng thành thật mà có vẻ lộn xộn hơn những gì bạn đã có.

Nếu cấu trúc dữ liệu không quan trọng, và bạn chỉ cần dữ liệu và có thể chơi với nó khi bạn thấy vừa vặn, tôi có thể liệt kê nó vào một từ điển. Tất nhiên, đó là khá chặt chẽ cùng với những gì bạn đã có bây giờ, mà có vẻ như đó là một thực hiện giả anyway.

Nếu bạn muốn làm điều đó, nó khá đơn giản. Đó là lựa chọn của bạn cách bạn tạo ra IEnumerable<string> được thể hiện bên dưới là entityNames. Bạn có thể sử dụng một bộ khởi tạo mảng như tôi làm, bạn có thể sử dụng một List<string> mà bạn xây dựng theo thời gian, thậm chí bạn có thể yield return nó theo phương pháp riêng của nó.

var entityNames = new[] { "EntityName1", "EntityName2", "EntityName3" }; 

var dict = entityNames.ToDictionary(c => c, c => GetByName(c)); 

Sau đó, đó chỉ là vấn đề kiểm tra chúng.

var entity1 = dict["EntityName1"]; 

Hoặc liệt kê qua từ điển.

foreach(var kvp in dict) 
{ 
    Console.WriteLine("{0} - {1}", kvp.Key, kvp.Value); 
} 

Nhưng thực tế, thật khó để biết liệu đó là thích hợp hơn với những gì bạn đã có.

3

Ok, đây là một ý tưởng.

Bạn có thể khai báo hàm này.

IReadOnlyDictionary<string, T> InstantiateByName<T>(
     Func<string, T> instantiator 
     params string[] names) 
{ 
    return names.Distinct().ToDictionary(
     name => name, 
     name => instantiator(name)) 
} 

mà bạn có thể gọi như thế này,

var entities = InstantiateByName(
     GetByName, 
     "EntityName1", 
     "EntityName2", 
     "EntityName3"); 

Để đẩy quá kỹ thuật để cấp độ tiếp theo,

bạn có thể cài đặt các bộ sưu tập gói Immutable,

PM> Install-Package Microsoft.Bcl.Immutable 

và sửa đổi chức năng hơi,

using Microsoft.Immutable.Collections; 

IReadOnlyDictionary<string, T> InstantiateByName<T>(
     Func<string, T> instantiator 
     params string[] names, 
     IEqualityComparer<string> keyComparer = null, 
     IEqualityComparer<T> valueComparer = null) 
{ 
    if (keyComparer == null) 
    { 
     keyComparer = EqualityComparer<string>.Default; 
    } 

    if (valueComparer == null) 
    { 
     valueComparer = EqualityComparer<T>.Default; 
    } 

    return names.ToImmutableDictionary(
     name => name, 
     name => instantiator(name), 
     keyComparer, 
     valueComparer); 
} 

Chức năng sẽ được sử dụng theo cách giống hệt nhau. Tuy nhiên, người gọi có trách nhiệm truyền các khóa duy nhất cho hàm nhưng, một trình so sánh bình đẳng thay thế có thể được thông qua.

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