Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by LaneFox · Jun 01, 2015 at 07:01 PM · listsdictionarylinq

Some Dictionary LINQ functions not cooperating?

I can't seem to figure out why some of these expressions are not working. I'm getting Null errors. Even foo.Any() gives me a 'cannot be null' error. Why?

The idea with this code is for an AI to find nearby allies, check their Threat List, see if their biggest threat is bigger than its own current threat, then adopt it if so.

Subject is the base class of entities.

Intellect is the AI which contains the lists/dictionaries.

Problematic section of code:

             foreach (Intellect buddy in AllyList
                 .Select(ally => ally.GetComponent<Intellect>())
                 .Where(buddy => buddy.ThreatList.Any())
                 .Where(buddy => buddy.ThreatList.Max().Value > myThreat[0].Value))
             {
                 myThreat[0] = buddy.ThreatList.Max();
             }

And here is an alternative I tried. They are the same, and both give me the error.

             foreach (Subject ally in AllyList)
             {
                 Intellect buddy = ally.GetComponent<Intellect>();
                 if (buddy.ThreatList.Any())
                 {
                     if (buddy.ThreatList.Max().Value > myThreat[0].Value)
                     {
                         myThreat[0] = buddy.ThreatList.Max();
                     }
                 }
             }


This is the error:

 ArgumentNullException: Argument cannot be null.
 Parameter name: source
 System.Linq.Check.Source (System.Object source)
 System.Linq.Enumerable.Any[KeyValuePair`2] (IEnumerable`1 source)
 Deftly.Intellect.GetHighestThreat () (at Assets/Deftly/Scripts/Intellect.cs:495)
 Deftly.Intellect+<ProcessConditions>c__Iterator1.MoveNext () (at Assets/Deftly/Scripts/Intellect.cs:253)
 UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
 Deftly.<StateMachine>c__Iterator0:MoveNext() (at Assets/Deftly/Scripts/Intellect.cs:215)
 UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
 Deftly.Intellect:Start() (at Assets/Deftly/Scripts/Intellect.cs:141)


The error reports that it is the if (buddy.ThreatList.Any()) line but I've had issues using other methods to find out if there are no elements, like .Count... It does the same error if I use that.

Any idea why this is happening? Could this be a SEO issue? The script seems to run fine and this only occurs (once) in the rare case that one AI can see the player, which triggers these checks, but the other AI(s) cannot and therefore have empty ThreatLists but I assumed the .Any() or .Count > 0 checks would prevent that error.

Comment
Add comment · Show 4
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image tanoshimi · Jun 01, 2015 at 07:05 PM 0
Share

I'm not familiar with .Any(). How does it differ from .Count() > 0 ?

avatar image LaneFox · Jun 01, 2015 at 07:57 PM 0
Share

.Any() returns a bool based on if the source has any elements.

avatar image tanoshimi · Jun 01, 2015 at 08:04 PM 0
Share

So, the answer to my question is... "it doesn't" :)

avatar image LaneFox · Jun 01, 2015 at 08:21 PM 0
Share

Which is why above, i say they're the same and i tried not using .Any() to see if the issue was related to the LINQ expression.

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Baste · Jun 02, 2015 at 09:06 AM

The any method is documented like this:

 public static bool Any<TSource>(
     this IEnumerable<TSource> source,
     Func<TSource, bool> predicate
 )
 
 ...
 
 throws ArgumentNullException if source or predicate is null.

In your case, the predicate is not null, as it's a lambda. Your error log should also be a hint, as it says "Parameter name: source"

This means that your AllyList is null. If Linq had been "normal" methods, you'd have gotten a NullReferenceException, but since they're extension methods, they get re-written into static method calls, and you get the ArgumentNullException instead.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image LaneFox · Jun 02, 2015 at 11:23 AM 0
Share

Hmm, I see what you mean but still don't fully understand why its happening.

As far as I can tell, the error seems to happen when an AI has one threat but its neighbor Ally that it queries does not have any threats... however I only see it once in the console so I'm not sure if it is because it stops or if it actually only happens one time... Like for instance the Intellect script hadn't initiated on the Ally before it was queried for threats?

If the actual List is null then that must be true and I'm not really sure how to address the issue. SEO is setup properly for this but it seems like one Intellect is processing entirely before the other can initiate.

avatar image Baste · Jun 02, 2015 at 06:02 PM 0
Share

Looking over your code again, I kinda messed up. It's not the AllyList that's null, it's the buddy.ThreatList that's null, as it's the one getting called .Any on.

Still, Any() throws the error if it's called on a null-object. I can see two solutions:

1: ensure that the ThreathList is instantiated in Awake, and that this method is not called in any Awake calls. Then you'll be sure that the ThreathList is always instantiated when it's needed.

In general, you should create everything that can be created internally in a class in Awake, and create everything that requires other objects to exist in Start.

2: make the ThreathList lazy. If it's not a public variable that you need to put stuff in from the inspector, you can declare it like this, assu$$anonymous$$g it's a list of Subject:

 public List<Subject> ThreathListBacker;
 public List<Subject> ThreathList {
     get {
         if(ThreathListBacker == null)
             ThreathListBacker = new List<Subject>();

         return ThreathListBacker;
     }
 }

Then it will always exist when you need it. I like this pattern - you don't get these really big constructors (normal classes) or Awake methods ($$anonymous$$onoBehaviours) that sets up everything

avatar image LaneFox · Jun 03, 2015 at 12:23 AM 0
Share

There we go I was doing init with Start(), just moved relevant stuff to Awake() and its working fine! No errors.

The 2nd approach is interesting too, but I'm not as familiar with pros and cons of properties like that so I'll stay as is for the time being =)

Thanks for the help!

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

3 People are following this question.

avatar image avatar image avatar image

Related Questions

Understanding Linq and orderbydescending 1 Answer

Strange Behavior with Dictionary of List of generic Actions 0 Answers

How to add dictionary keys with defined values to a list 1 Answer

Dictionary Keys to Stack Enemy Types 1 Answer

Dictionary key exists but corresponding value pair is non-existent 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges