C#:最简单的初始化方式&填充这个特定的2D / 3D字典?

时间:2017-09-18 02:25:16

标签: c# dictionary containers game-engine

我有一点复杂的字典。

这是一本包含两种枚举类型的字典。列表<>

\r

因此,当我想使用它时,我会这样做:

Dictionary<BiomeType, Dictionary<LocationType, List<string>>> myDictionary;

当我尝试将“myString”添加到myList时,它会抛出一个明显的&amp;可预见的错误:“KeyNotFoundException:字典中没有给定的密钥。”

C#中是否有任何方法可以自动让Dictionary添加Key(如果还没有)?我有很多BiomeTypes&amp;甚至更多的LocationTypes。 PITA必须创建每个List,然后创建每个locationtype字典,然后为每个BiomeType添加它。所有这些只是为了初始化这个复杂的字典。有没有简单的方法可以做到这一点?

我正在将它用于gamedev,将对象存储在Dictionary中,所以我可以通过执行类似

的操作来访问它们
//Add "myString" to the List<string>
myDictionary[BiomeType.Jungle][LocationType.City1].Add("myString"));

4 个答案:

答案 0 :(得分:1)

也许,你可以试试这个:

    import React from 'react';
    import ReactDom from 'react-dom';
    import { createStore, applyMiddleware, combineReducers } from 'redux';
    import { Provider } from 'react-redux';
    import { Router, Route, IndexRoute, hashHistory } from 'react-router';
    import { syncHistoryWithStore, routerReducer } from 'react-router-redux';
    import thunkMiddleware from 'redux-thunk';

    import reducers from './redux/reducers';
    import Entrance from './components/Entrance.jsx';
    import EntranceNone from './components/EntranceNone.jsx';
    import CreditPoints from './components/CreditPoints.jsx';
    import CreditPrivilege from './components/CreditPrivilege.jsx';
    import CreditPromote from './components/CreditPromote.jsx';

    let reduxDevTool = null;
    let combReducer = { app: reducers, routing: routerReducer };
    let store = createStore(combineReducers(combReducer), applyMiddleware(thunkMiddleware));

    const history = syncHistoryWithStore(hashHistory, store);

    ReactDom.render(
        <Provider store={store}>
            <div>
                <Router history={history}>
                    <Route path="/" component={ Entrance }></Route>
                    <Route path="/EntranceNone" component={ EntranceNone }></Route>
                    <Route path="/creditPoints" component={ CreditPoints }></Route>
                    <Route path="/privilege" component={ CreditPrivilege }></Route>
                    <Route path="/promote" component={ CreditPromote }></Route>
                </Router>
            </div>
        </Provider>,
        document.getElementById('app')
    );


require('../less/entrance.css');
import { initRootFontSize,originDomin } from '../utils';
import React,{Component} from 'react';
import classNames from 'classnames';
import 'babel-polyfill';
import cookie from 'react-cookie';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as Actions from '../redux/action';
import { hashHistory ,Link } from 'react-router';

class Entrance extends Component { 
    constructor (props) {
        super(props);
        initRootFontSize();
        this.state = {
            agree:true,
            submitFlag:false
        };
    }

    handleAgreeMent(){
        this.setState({agree:!this.state.agree});
    }

    componentDidMount(){
        if(creditData.isOpenCreditService === "0"){
            this.context.router.push('/');
        }else{
            this.context.router.push('/creditPoints');
        }
    }

    componentDidUpdate(prevProps,prevState){
        if(this.props.resCode && this.state.submitFlag){
            if(this.props.resCode == "000"){
                this.context.router.push('/creditPoints');
            }else{
                alert(this.props.resMsg);
            }
        }
    }

    handleClick(){
        if(this.state.agree){ 
            this.props.actions.fetchIsOpen();
            this.setState({submitFlag:true}); 
        }
    }

    render () {   
        return(
            <div className="wrap">
                <div className="credit-img"></div>
                <div className="credit-cont">
                    <p className="credit-cont-up">xxx</p>
                    <p className="credit-cont-down">xxx</p>
                </div>
                <div className="credit-agree"><span className={classNames({icon: true, iconSelected: this.state.agree})} onClick={this.handleAgreeMent.bind(this)}></span><span className="credit-agree-cont">xx<a href={originDomin()+'static.pay.xiaomi.com/mi-credit-points/src/html/agreeMent.html'} className="credit-agree-detail">xxx</a></span></div>
                <div className={classNames({button: true,bottonFalse:this.state.agree,submitFlag:this.state.submitFlag})}  onClick={this.handleClick.bind(this)}>{this.state.submitFlag?'x':'xx'}</div>
            </div>
        );
    }

}

function mapStateToProps(state) {
    return {
        resCode: state.app.resCode,
        resMsg: state.app.resMsg,
        dataList: state.app.dataList
    };
}

function mapDispatchToProps(dispatch) {
    return {
        actions: bindActionCreators(Actions, dispatch),
    };
}

Entrance.contextTypes = {
    router: React.PropTypes.object
};

export default connect(mapStateToProps, mapDispatchToProps)(Entrance);

答案 1 :(得分:1)

你可以这样做(虽然老实说我不确定你应该这样做!)

下面的类是一种类型,通常像字典一样,按照你的要求行事,并进行一些其他更改,以便在每次向索引器询问没有的项目时隐藏它所创建的空白项目。存在。

public class SmellyDictionary<T1, T2>: IDictionary<T1, T2>, ICollection where T2 : ICollection, new()
{
    private readonly IDictionary<T1, T2> _dict = new Dictionary<T1, T2>();

    public T2 this[T1 key]
    {
        get
        {
            T2 value;
            if (!_dict.TryGetValue(key, out value))
                _dict[key] = value = new T2(); // This stinks!
            return value;
        }
        set { _dict[key] = value; }
    }

    public bool Contains(KeyValuePair<T1, T2> item)
    {
        return _dict.Contains(item);
    }

    public bool ContainsKey(T1 key)
    {
        return _dict.ContainsKey(key) && _dict[key].Count > 0; // This hides the smell
    }

    public int Count { get { return _dict.Count(kvp => kvp.Value.Count > 0); } } // This hides the smell

    public void Add(T1 key, T2 value)
    {
        T2 currentValue;
        if (_dict.TryGetValue(key, out currentValue) && currentValue.Count > 0)
            throw new ArgumentException("A non empty element with the same key already exists in the SmellyDictionary");
        _dict[key] = value;
    }

    public void Add(KeyValuePair<T1, T2> item)
    {
        Add(item.Key, item.Value);
    }

    public bool Remove(T1 key)
    {
        return _dict.Remove(key);
    }

    public bool Remove(KeyValuePair<T1, T2> item)
    {
        return _dict.Remove(item);
    }

    public bool TryGetValue(T1 key, out T2 value)
    {
        return _dict.TryGetValue(key, out value);
    }

    public ICollection<T1> Keys { get { return _dict.Keys; } }
    public ICollection<T2> Values { get { return _dict.Values; } }
    public object SyncRoot { get { return ((ICollection)_dict).SyncRoot; } }
    public bool IsSynchronized { get { return ((ICollection)_dict).IsSynchronized; } }

    public IEnumerator<KeyValuePair<T1, T2>> GetEnumerator()
    {
        return _dict.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public void Clear()
    {
        _dict.Clear();
    }

    public void CopyTo(Array array, int index)
    {
        _dict.CopyTo((KeyValuePair<T1, T2>[])array, index);
    }

    public void CopyTo(KeyValuePair<T1, T2>[] array, int arrayIndex)
    {
        _dict.CopyTo(array, arrayIndex);
    }

    public bool IsReadOnly { get { return _dict.IsReadOnly; } }
}

答案 2 :(得分:1)

这是一个更明智的选择。只需调用此方法即可将字符串添加到字典中。

    private void AddCityToDictionary(Dictionary<BiomeType, Dictionary<LocationType, List<string>>> myDictionary, BiomeType biome, LocationType location, string city)
    {
        Dictionary<LocationType, List<string>> locationDictionary;
        if (!myDictionary.TryGetValue(biome, out locationDictionary))
            locationDictionary = myDictionary[biome] = new Dictionary<LocationType, List<string>>();
        List<string> cityList;
        if (!locationDictionary.TryGetValue(location, out cityList))
            cityList = locationDictionary[location] = new List<string>();
        cityList.Add(city);
    }

答案 3 :(得分:0)

简单地循环遍历每个可能的枚举类型&amp;添加新值可以完全填充此多维字典。

    Dictionary<BiomeType, Dictionary<LocationType, List<string>>> myDictionary = new Dictionary<BiomeType, Dictionary<LocationType, List<string>>>(); //No thanks to troll users like Peter.
    foreach (BiomeType biomeType in System.Enum.GetValues(typeof(BiomeType)))
    {
        Dictionary<LocationType, List<string>> newLocDict = new Dictionary<LocationType, List<string>>(); //No thanks to troll users like Peter.

        foreach (LocationType locType in System.Enum.GetValues(typeof(LocationType)))
        {
            List<string> newList = new List<string>(); 
            newLocDict.Add(locType, newList); //Add the final bit here & voila! Finished! No thanks to troll users like Peter.
        }

        myDictionary.Add(biomeType, newLocDict);
    }

如果您不想使用ALL枚举值完全填充容器,Robyn的解决方案的工作方式相同。