2011-09-07 3 views
4

.NET 배열은 C#에서 다음 작품, 공변 때문에 :배열 공분산

F 번호에
var strArray = new string[0]; 
object[] objArray = strArray; 

, 다시없이 obj[]로 변환하는 가장 좋은 방법 일 것입니다 무슨 배열, 'T[]을, 주어진 어레이 (예 : Array.map box) 만들기? (box >> unbox)을 사용하고 있지만 엉성함이 느껴집니다.

+3

흥미 롭습니다. 나는 C#에 대해 이것을 몰랐다. 이것은 정적 유형 안전을 손상시키는 잘못된 기능입니까? – wmeyer

+2

@wmeyer : http://stackoverflow.com/q/3516619/162396; http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx – Daniel

+1

사실 제네릭에 매우 유용합니다. 비 제네릭 인터페이스를 구현하는 클래스. – Daniel

답변

3
box >> unbox 

은 좋은 생각입니다. O (1), 그리고 분명히 일을합니다.

이 CLR 잘못 기능을 사용하지 않는 것도 고려하십시오. ;)

+2

나는'Array.map box '를 사용할 수 있다고 생각하지만, 완벽하게 좋은 잘못된 기능을 사용할 수있을 때 배열을 다시 만드는 것이 잘못되었다고 생각합니다. ;-) – Daniel

3

브라이언의 솔루션은 나에게 잘 보이지만 실제로 배열 공분산이 필요합니까?

당신이 ISomething[]을 소요하고 당신이 그것을 필요로 다음을 SomeSomething[]를 전달하려는하지만, 함수는 배열에서 유형 ISomething의 값을 읽는 경우 (공분산이 허용하는 것입니다) 기능이있는 경우, 당신은 해시를 사용할 수 있습니다 -type을 입력하고 #ISomething[]을 사용하는 함수를 작성하십시오.

이렇게하면 ISomething을 구현하는 모든 요소의 배열에서 함수가 작동 할 수 있으며 호출 할 때 배열 공분산이 필요하지 않습니다. .NET에서 배열 공분산의 주된 이유는 그것이 제네릭이 존재하지 않는 시간에 필요하다는 것을

type A() = 
    interface IDisposable with 
    member x.Dispose() = printfn "gone" 

// Disposes the first element from an array 
let disposeFirst (a:#IDisposable[]) = a.[0].Dispose() 

// Call 'disposeFirst' with 'A[]' as an argument 
let aa = [| new A(); new A() |] 
disposeFirst aa 

그것은 나에게 보인다, 그러나 F 번호가이 기능없이 살 수있는 것 같다 예를 들면 다음과 같습니다 잘 됐네.

+0

타입 멤버가'T []'인 제네릭 타입을 사용하여'obj []'를 반환하는 인터페이스 멤버를 구현하는 방법은 무엇입니까? 인터페이스는''T'에 대해 알지 못하므로 해시 유형이 도움이 될지는 알 수 없습니다. – Daniel

+0

@ 대니얼 - 시나리오를 잘 모르겠습니다. 몇 가지 예를들 수 있습니까? 해시 타입은 함수를 generic으로 만들고'obj []'뿐만 아니라'foo'가'obj'를 상속하는 foo []'도 취할 수있게 해줍니다. 이것은 배열 공분산이하는 것과 같은 것입니다 ... –

+0

인터페이스 (generic이 아닌)는'obj []'타입의 멤버를 가지고있다. 장애물은 해시 유형을 사용하면 둘러싸는 유형이 일반화된다는 것입니다. 그러나 인터페이스 *를 구현하는 클래스는 * generic입니다 (해당 멤버의 형식은'[T []'). – Daniel

4

브라이언이 말한 것처럼 box >> unbox에는 아무런 문제가 없습니다. 다른 점은 배열 공분산이 본질적으로 손상된다는 것입니다 (예 : ([| "test" |] |> box |> unbox<obj[]>).[0] <- obj()은 할당을 수행하려고 할 때 ArrayTypeMismatchException을 발생시킵니다). (여전히 F 번호가 일반적인 공동/콘트라 분산을 지원하지 않기 때문에 F 번호 복싱과 언 박싱을 필요로하지만)

대신, 당신은 아마 완벽하게 안전 인 obj seq, 같은 string[]을 치료하는 더 나을 것입니다. 불행히도이 경로를 사용하면 임의 액세스를 잃게됩니다.

+0

그리고 불행히도 나는 임의 접근이 필요하다. 아마도 더 큰 문제는 array 타입의 비 제네릭 인터페이스 멤버를 구현하는 방법 일 것입니다. 내 인터페이스는 "항목의 페이지 된 목록"(항목 및 페이징 정보)입니다. 따라서 배열 요소는 모든 유형이 될 수 있습니다. 그렇지 않으면 배열 요소를 나타내는 또 다른 인터페이스를 발명 할 것입니다. 나는 그것이 바람직한 해결책이라고 생각합니다. – Daniel

+1

@Daniel - 이상적으로, BCL은 공변적이고't [] '에서 파생 된'ReadOnlyArray <'t>'유형을 포함합니다. 이후, 당신은 덜 바람직한 옵션으로 제한됩니다. 배열 공분산을 사용하면 변환 된 배열에 쓰지 않는 것을 잊지 않는 한 괜찮습니다 ... – kvb

+2

ReadOnlyArray를 기록했습니다. 투표하십시오! http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2235515-readonly-array – Brian