2

次のような状況があり、混乱しています。

与えられた:

public class ThermoRawFile : MsDataFile { }

public abstract class MSDataFile { }

この LINQ IEnumerable.ToDictionary() メソッドを実行できません。

IEnumerable<string> rawFiles;
Dictionary<string, MSDataFile> dataFiles = rawFiles.ToDictionary(
    file => file,
    file => new ThermoRawFile(file)
);

コンパイラが次のエラーを出すため:

"Cannot implicitly convert type System.Collections.Generic.Dictionary<string,CSMSL.IO.Thermo.ThermoRawFile> to System.Collections.Generic.Dictionary<string,CSMSL.IO.MSDataFile>"

単純な継承であるのに、なぜ暗黙的に変換できないThermoRawFileのですか?MSDataFile

これはうまくいきます:

 MSDataFile dataFile = new ThermoRawFile("someFile.raw");
4

3 に答える 3

3

The problem is that type inference has inferred your ToDictionary call to be:

rawFiles.ToDictionary<string, string, ThermoRawFile>(...)

That means the returned value will be of type Dictionary<string, ThermoRawFile>, and there's no conversion from that to Dictionary<string, MSDataFile> (partly because dictionaries are invariant in general, and partly because all classes are invariant).

Now you can cast the value selection part to make type inference work:

var dataFiles = rawFiles.ToDictionary(
    file => file,
    file => (MSDataFile) new ThermoRawFile());

Or you could just explicitly specify the type arguments:

var dataFiles = rawFiles.ToDictionary<string, string, MSDataFile>(
    file => file,
    file => new ThermoRawFile());

That will still be fine, as the compiler can convert the lambda expression file => new ThermoRawFile() into a Func<string, MSDataFile>.

于 2013-09-06T16:46:51.267 に答える
3

このエラーは、 に変換できないことを示しているのではなく、 に基づくジェネリック ディクショナリ タイプを に基づくジェネリック ディクショナリ タイプに変換できないCSMSL.IO.Thermo.ThermoRawFileことCSMSL.IO.MSDataFileだけを示しています。これらの型は共変ではないため、これは予期されることです。CSMSL.IO.Thermo.ThermoRawFileCSMSL.IO.MSDataFile

キャストを提供することでこれを修正できます。

IEnumerable<string> rawFiles;
Dictionary<string, MSDataFile> dataFiles = rawFiles.ToDictionary(
    file => file,
    file => (MSDataFile)new ThermoRawFile(file)
);
于 2013-09-06T16:41:49.450 に答える
0

これは共分散と関係があります。AThermoRawFileは ですがMSDataFile、aDictionary<string, ThermoRawFile>は ではありませんDictionary<string, MSDataFile>

もしそうなら、あなたは次のようなことをすることができます:

public class FooFile : MsDataFile { }

dataFiles["blah"] = new FooFile();

これは aFooFileを aに入れることになりDictionary<string, ThermoRawFile>、あらゆる種類の大混乱を引き起こします。

この場合Dictionary<string, MSDataFile>、完全にThermoRawFile値を入力したとしても、最初から実際の型の辞書を作成する必要があります。キャストを追加することでこれを行うことができます(ここにある他の多くの回答に示されているように):

IEnumerable<string> rawFiles;
Dictionary<string, MSDataFile> dataFiles = rawFiles.ToDictionary(
    file => file,
    file => (MSDataFile)new ThermoRawFile(file)
);
于 2013-09-06T16:47:53.713 に答える